2017-08-04 77 views
0

使用下面的代碼,我總是得到0作爲第一個輸出。這有保證嗎?Java Stream'peek'是在終端操作之前還是之後發生?

import java.util.Random; 
    import java.util.stream.Stream; 

    public class Main { 

    public static void main(String[] args) { 
     Main m = new Main(); 
     m.rope(); 
    } 


    class Wrapper { 
     public int x = 0; 
    } 


    void rope() { 
     Stream.generate(Wrapper::new).limit(100000) 
       .peek(w -> asum += w.x) 
       .forEach(w -> mutate(w)); 

     System.out.println(asum); 
     System.out.println(bsum); 
    } 


    void mutate(Wrapper w) { 
     w.x = r.nextInt(2); 
     bsum += w.x; 
    } 


    protected long asum = 0; 
    protected long bsum = 0; 
    Random r = new Random(0); 
} 

根據「偷看」的文件「...... 元素消耗每個元素執行所提供的行動......」。但對於非平行流,它必須在之前或之後。

換言之,當「終端操作」發生了一個元件被它從終端操作之前或之後的管道刪除?

(我敢肯定,「前」是正確的答案,而是試圖理解一些複雜的流代碼,其中相反似乎假設。)

+1

切圓,其接受一個函數的流操作的所有指定的功能應該是[非干擾(https://docs.oracle.com/javase/8/docs/api/java/util/stream/package -summary.html#互不干擾)。這意味着,在界面層面,如果發現未知的情況,可以安全地離開。 –

回答

1

想想吧。如果你有一個流的管道像

...peek(xxx).map(...).peek(yyy).collect(...)

xxx代碼將看到應用映射功能之前的元素yyy代碼將看到該元素應用映射功能後,和之前的元素被越區切換到最終的操作,如元素「流動」往下流。

的特定元素將通過在流管道的順序流的步驟進行處理,但一般有不同的元素的順序上沒有任何約束被處理,特別是如果流是平行的。

E.g.流引擎可以決定將所有元素髮送到xxx代碼,映射所有元素之前,最後發送到yyy代碼的所有元素。如果有的話,流管道將正常工作。它不會,或者當然不會,因爲這會破壞流式傳輸的目的,但它會有效地執行。

+0

謝謝。那麼,推廣流操作是否保證按照它們被指定的順序被應用是正確的,而不管運算符名稱如何,只要**單個**輸入元素被關心?當然,當一個操作的'輸出'是下一個操作的輸入時,情況就是這樣,但我不確定輸入和輸出是否相同的操作。 – Jeevaka

+1

@Jeevaka正確。 – Andreas

+1

@Jeevaka:如果它能夠改變其在加工鏈中的地位,那麼即使是爲了它的預期目的,「偷看」也是毫無用處的。但是這並不能改變這樣一個事實,即在你的問題代碼中使用它是非常令人沮喪的。 – Holger

1

peek功能將始終在函數之前調用每個元素爲forEach

相關問題