2014-01-19 165 views
18

我从java 8 API流上的抽象,但 读书,我不明白这句话非常好:流和懒惰评估

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

当过滤器操作创建新的流时,该流是否包含过滤的元素? 似乎了解,流只包含遍历的元素,即使用终端操作。但是,比什么包含过滤的流?我很困惑!!!

+0

@Lukas,我们已经为Java 8 Stream API提供了[tag:java-stream]。您创建的标签非常...通用。 – Charles

+9

但它的正式名称是“Streams API”,而不是“Java-Stream”。 Java Stream可以表示任何东西。包括InputStream/OutputStream等。无论如何,我想这应该采取元... –

回答

27

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

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; 
} 

(无法编译,是现实的简化,但原则是存在的)

3

流是懒惰的,因为除非是调用终端操作中间业务不被评估。

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

流水线累积了这些新创建的流。

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

并行流不会逐个评估流(在终点)。这些操作是同时执行的,取决于可用的内核。

1

在我看来,这中间操作中不完全懒:

List<String> l3 = new ArrayList<String>(); 
     l3.add("first"); 
     l3.add("second"); 
     l3.add("third"); 
     l3.add("fouth"); 
     l3.add("fith"); 
     l3.add("sixth"); 

     List<String> test3 = new ArrayList<String>(); 
     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 

貌似对流创建迭代套数,但歌厅一个新的流元素懒惰。

+0

你可以请格式化您的代码,突出显示它,并按Ctrl + K – WhatsThePoint