将List传输到Java流中,然后删除List中的一个元素.出现一些错误


List<String> list = new ArrayList(){{add("apple");add("banana");add("orange");}};
Stream<String> stringStream = list.stream();
stringStream.forEach(
m->{
if (m.equals("banana")){
list.remove("banana");
}
}
);
System.out.println(stringStream.count());

最后,控制台打印一个NullPointerException错误。CoreJava说我们不应该修改Collection,它将在修改后返回流。而且我对这个原理没有一个清晰的理解。

传递给forEachConsumer必须是无干扰的。其理由如下所述。

无干扰

流使您能够对各种数据源执行可能的并行聚合操作,甚至包括ArrayList等非线程安全集合。只有当我们能够在流管道的执行过程中防止对数据源的干扰时,这才有可能。除了转义填充操作迭代器((和拆分器((之外,执行从调用终端操作时开始,到终端操作完成时结束对于大多数数据源,防止干扰意味着确保数据源在流管道执行过程中不会被修改。值得注意的例外是,流的源是并发集合,它们是专门为处理并发修改而设计的。并发流源是指Spliterator报告具有并发特性的流源。

(来源(

顺便说一句,即使上一个stringStream.forEach()语句没有,您的stringStream.count()也会失败,因为forEach(与任何终端操作一样(会消耗Stream,而Stream不能消耗两次。

实现您想要做的事情的正确方法是过滤原始的List并创建新的List:

List<String> filtered = 
list.stream()
.filter(m->!m.equals("banana"))
.collect(Collectors.toList());

不能使用流从列表中删除元素,但可以通过调用removeIf()来使用lambda表达式。

List<String> list = new ArrayList<>(Arrays.asList("apple", "banana", "orange"));
list.removeIf(m -> m.equals("banana")); // or: list.removeIf("banana"::equals)
System.out.println(list); // prints: [apple, orange]
System.out.println(list.size()); // prints: 2
List<String> list = new ArrayList<>() 
{
{
add("apple");add("banana");add("orange");
}
};
Stream<String> stringStream = list.stream();
final long counter = stringStream.filter(Predicate.not("banana"::equals))
.count();
System.out.println(counter);

最新更新