将列表传输到Java流中,然后删除列表中的元素。发生某些错误

jfh*_*ang 7 java java-8 java-stream

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());
Run Code Online (Sandbox Code Playgroud)

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

Era*_*ran 11

Consumer传递给forEach必须是互不干扰。解释如下。

不干涉

流使您可以对各种数据源执行可能并行的聚合操作,甚至包括非线程安全的集合(例如ArrayList)。这只有在我们可以防止流管道执行期间干扰数据源的情况下才有可能。除了转义hatch操作iterator()和spliterator()之外,执行都在调用终端操作时开始,并在终端操作完成时结束。对于大多数数据源,防止干扰意味着确保在执行流水线期间根本不修改数据源。值得注意的例外是其源是并发集合的流,这些流是专门为处理并发修改而设计的。并发流源是那些其分隔符报告CONCURRENT特性的源。

来源

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

实现您要执行的操作的正确方法是过滤原始文件List并创建一个新文件List

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