我们现在看两个问题:
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的执行过程,才能够写出来简洁正确的程序。