Java 8 在List和Set接口中引入了几种方法:
- removeIf 删除满足条件的元素。 所有实现List或Set的类均可用。
- replaceAll在List上可用,并使用(UnaryOperator)替换元素功能。
- sort在List接口上可用,对列表本身进行排序。
与Steam操作不同,它们会更改集合本身,而Steam操作会产生新的复制结果。
removeIf
举个🌰,下面的代码删除数字开头的事物:
for (Transaction transaction : transactions) {
if(Character.isDigit(transaction.getReferenceCode().charAt(0))) {
transactions.remove(transaction);
}
}
上面的写法可能会导致ConcurrentModificationException。如果我们使用下面代码,通过for-each循环使用Iterator对象:
for (Iterator<Transaction> iterator = transactions.iterator(); iterator.hasNext(); ) {
Transaction transaction = iterator.next();
if(Character.isDigit(transaction.getReferenceCode().charAt(0))) {
transactions.remove(transaction);
}
}
注意下面两种独立的管理集合操作:
- Iterator 对象, 使用next() 和 hasNext() 访问元素
- Collection 对象本身, 使用 remove() 删除元素
Iterrator的状态不再与集合的状态同步,反之亦然。 要解决此问题,我们必须显式使用Iterator对象并调用其remove()方法:
for (Iterator<Transaction> iterator = transactions.iterator(); iterator.hasNext(); ) {
Transaction transaction = iterator.next();
if(Character.isDigit(transaction.getReferenceCode().charAt(0))) {
iterator.remove();
}
}
这种写法看起来非常冗余,现在我们可以使用Java 8 的 removeIf 方法直接表达逻辑,不仅简单,而且可以避免出错。代码如下:
transactions.removeIf(transaction -> Character.isDigit(transaction.getReferenceCode().charAt(0)));
replaceAll
可以使用 replaceAll 拿新元素替换 List 中的每个元素。
首先是一个使用Streams API的例子:
referenceCodes.stream()
.map(code -> Character.toUpperCase(code.charAt(0)) +
code.substring(1))
.collect(Collectors.toList())
.forEach(System.out::println);
上面的此代码生成了一个新的字符串集合。如果需要更新现有集合,旧版Java中可以按如下方式使用ListIterator对象来替换元素:
for (ListIterator<String> iterator = referenceCodes.listIterator(); iterator.hasNext(); ) {
String code = iterator.next();
iterator.set(Character.toUpperCase(code.charAt(0)) + code.substring(1));
}
这段代码非常冗长,同样的,将Iterator对象与集合对象结合使用可能容易出错。 在Java 8中,我们可以简单地编写下面的代码
referenceCodes.replaceAll(code -> Character.toUpperCase(code.charAt(0)) + code.substring(1));
评论