2017-08-04 57 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

相关问题