java8 stream pipelines中 skip 和 limit 执行过程深入理解


我们现在看两个问题:
Stream.of(1,2,3,4,5)
        .peek(x->System.out.print("\nA"+x))
        .limit(3)
        .peek(x->System.out.print("B"+x))
        .forEach(x->System.out.print("C"+x));
输出为:
A1B1C1
A2B2C2
A3B3C3
------------------------------------------------------------------------------------------------

Stream.of(1,2,3,4,5)
        .peek(x->System.out.print("\nA"+x))
        .skip(3)
        .peek(x->System.out.print("B"+x))
        .forEach(x->System.out.print("C"+x));
输出为:
A1
A2
A3
A4B4C4
A5B5C5

这里有两个stream pipelines。
分别是两个数据源,包括一系列的中间操作,和最后的最终操作。
但是中间操作是lazy的,也就是中介操作不会对数据做任何操作,直到遇到了最终操作。

最终操作,都是比较热情的。他们会往前回溯所有的中间操作。
也就是当执行到forEach操作的时候,他会回溯到他的上一步中间操作,上一步中间操作,又会回溯到上上一步的中间操作,等等,直到最初的第一步。下面让我们分析下上面的第一个stream pipeline 。

Stream.of(1,2,3,4,5)
        .peek(x->System.out.print("\nA"+x))
        .limit(3)
        .peek(x->System.out.print("B"+x))
        .forEach(x->System.out.print("C"+x));

第一次forEach发的时候,会回溯peek 操作,然后peek会回溯更上一步的limit操作,然后limit会回溯更上一步的peek操作,,顶层没有操作了,开始自上向下开始执行,输出结果:A1B1C1

第二次forEach的时候,然后会回溯peek 操作,然后peek会回溯更上一步的limit操作,然后limit会回溯更上一步的peek操作,,顶层没有操作了,开始自上向下开始执行,输出结果:A2B2C2

...

当第四次forEach发的时候,然后会回溯peek 操作,然后peek会回溯更上一步的limit操作,到limit的时候,发现limit这个job已经完成,这里就相当于break操作,跳出来。之后就不会再往上回溯了。


--------------------------------------------------------------------------------------------------------------------------

再来看下面这个
Stream.of(1,2,3,4,5)
        .peek(x->System.out.print("\nA"+x))
        .skip(3)
        .peek(x->System.out.print("B"+x))
        .forEach(x->System.out.print("C"+x));

第一次forEach触发的时候,会回溯peek 操作,然后peek会回溯更上一步的skip操作,skip回溯到上一步的peek操作,顶层没有操作了,开始自上向下开始执行,执行到skip的时候,因为执行到skip,这个job的意思就是跳过吧。下面的都不要执行了,就相当于continue了,结束本次foreach,执行下一次foreach。 输出A1

第二次forEach触发的时候,会回溯peek 操作,然后peek会回溯更上一步的skip操作,skip回溯到上一步的peek操作,顶层没有操作了,开始自上向下开始执行,执行到skip的时候,发现这是第二次skip,因为执行到skip就相当于continue了,结束本次foreach,执行下一次foreach。
输出A2

...

第四次forEach触发的时候,会回溯peek 操作,然后peek会回溯更上一步的skip操作,他知道,需要回溯上一步的peek操作,顶层没有操作了,开始自上向下开始执行,执行到skip的时候,发现这是第四次skip,已经大于3了,他已经执行完了skip的job了。 这次skip就直接跳过,继续执行下面的操作 。
输出A4B4C4

第五次forEach触发的时候,会回溯peek 操作,然后peek会回溯更上一步的skip操作,他知道,需要回溯上一步的peek操作,顶层没有操作了,开始自上向下开始执行,执行到skip的时候,发现这是第四次skip,已经大于3了,他已经执行完了skip的job了。 这次skip就直接跳过,继续执行下面的操作 。
A5B5C5

检验下是否真正理解了执行过程,我们替换一下skip的位置:

Stream.of(1,2,3,4,5)
        .peek(x->System.out.print("\nA"+x))
        .peek(x->System.out.print("B"+x))
        .skip(3)
        .forEach(x->System.out.print("C"+x));

输出结果为:

A1B1
A2B2
A3B3
A4B4C4
A5B5C5

想必这个结果,你应该很清楚了吧。


清晰的认识stream piplines的执行过程,才能够写出来简洁正确的程序。

猜你喜欢

转载自blog.csdn.net/zhangshk_/article/details/80744607