2014-01-19 166 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