Java Stream' peek'在终端操作之前或之后发生?

时间:2017-08-04 21:33:29

标签: java java-stream

使用以下代码,我总是得到0作为第一个输出。这有保证吗?

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

根据' peek'文档" ...对每个元素执行提供的操作作为元素被使用..."。但是对于非并行流,它必须在之前或之后。

换句话说,当'终端操作'对于一个元素,是在终端操作之前还是之后从管道中删除?

(我非常确定'之前是正确的答案,但试图了解一些复杂的流代码,其中似乎假设相反。)

2 个答案:

答案 0 :(得分:1)

peek中的函数将始终在forEach中的函数之前为每个元素调用。

答案 1 :(得分:1)

想一想。如果您有像

这样的流媒体管道

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

xxx代码会在应用映射函数之前看到元素,而yyy代码会在映射后看到元素函数被应用,元素被移交给最终操作之前, as 元素"流动"沿着溪流。

特定元素将按流管道顺序由流的步骤处理,但通常对正在处理的不同元素的顺序没有约束,特别是如果流是并行的。

E.g。在映射所有元素之前,流引擎可以决定将所有元素发送到xxx代码,然后最终将所有元素发送到yyy代码。如果确实如此,流管道将正常运行。它不会或当然,因为这会破坏流媒体的目的,但这样做有效