流和懒惰的评估

我正在阅读流抽象的java 8 API ,但我不太理解这句话:

中间操作返回一个新流。 他们总是懒惰; 执行诸如filter()之类的中间操作实际上并不执行任何过滤,而是创建一个新流,当遍历时,该流包含与给定谓词匹配的初始流的元素。 在执行管道的终端操作之前,不会开始遍历管道源。

当过滤操作创建新流时,该流是否包含过滤后的元素? 似乎理解流仅在遍历时才包含元素,即具有终端操作。 但是,包含过滤流的内容是什么? 我很困惑!!!

这意味着filter仅在终端操作期间应用。 想想这样的事情:

public Stream filter(Predicate p) { this.filter = p; // just store it, don't apply it yet return this; // in reality: return a new stream } public List collect() { for (Object o : stream) { if (filter.test(o)) list.add(o); } return list; } 

(这不编译,是对现实的简化,但原则是存在的)

流是惰性的,因为除非调用终端操作,否则不评估中间操作。

每个中间操作都会创建一个新流,存储提供的操作/function并返回新流。

管道累积这些新创建的流。

调用终端操作的时间,流的遍历开始,并且逐个执行相关的function。

并行流不会逐个评估流(在终端点)。 根据可用的核心,操作是同时执行的。

在我看来,中间操作并不完全是懒惰的:

 List l3 = new ArrayList(); l3.add("first"); l3.add("second"); l3.add("third"); l3.add("fouth"); l3.add("fith"); l3.add("sixth"); List test3 = new ArrayList(); try { l3.stream().filter(s -> { l3.clear(); test3.add(s); return true;}).forEach(System.out::println); } catch (Exception ex) { ex.printStackTrace(); System.out.println("!!! "); System.out.println(test3.stream().reduce((s1, s2) -> s1 += " ;" + s2).get()); } 

Otput:

  first null null null null null java.util.ConcurrentModificationException at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1380) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) at test.TestParallel.main(TestParallel.java:69) !!! first ;null ;null ;null ;null ;null 

看起来像流创建的迭代集的数量,但是新的流元素是懒惰的。