stream 中的foreEach()调用分析

2019-07-20  本文已影响0人  pengyuyancode

Stream.java对于forEach方法的解释:

为该流的每个元素执行一个操作。该方法是一个终止操作;对于并行流来说,遍历顺序可能是不准确的。对于共享变量的操作,需要提供额外的同步机制。

 /**
     * Performs an action for each element of this stream.
     *
     * <p>This is a <a href="package-summary.html#StreamOps">terminal
     * operation</a>.
     *
     * <p>The behavior of this operation is explicitly nondeterministic.
     * For parallel stream pipelines, this operation does <em>not</em>
     * guarantee to respect the encounter order of the stream, as doing so
     * would sacrifice the benefit of parallelism.  For any given element, the
     * action may be performed at whatever time and in whatever thread the
     * library chooses.  If the action accesses shared state, it is
     * responsible for providing the required synchronization.
     *
     * @param action a <a href="package-summary.html#NonInterference">
     *               non-interfering</a> action to perform on the elements
     */
void forEach(Consumer<? super T> action);

该方法有俩个实现

第一个位于 ReferencePipeline.java 中

@Override
public void forEach(Consumer<? super P_OUT> action) {
        evaluate(ForEachOps.makeRef(action, false));
}

第二个位于Head 中,它是ReferencePipeline.java 中的一个内部类

static class Head<E_IN, E_OUT> extends ReferencePipeline<E_IN, E_OUT> {
........
// Optimized sequential terminal operations for the head of the pipeline
        @Override
  public void forEach(Consumer<? super E_OUT> action) {
         if (!isParallel()) {
                sourceStageSpliterator().forEachRemaining(action);
         }
         else {
                super.forEach(action);
        }
 }
.......
}

现在有俩端代码

List<Integer> list= Arrays.asList(2,3,4,5,6);
list.stream().forEach(System.out::println);
List<Integer> list= Arrays.asList(2,3,4,5,6);
list.stream().map(item->item).forEach(System.out::println);

对于第一段代码stream.forEach(System.out::println),它会调用Head中的forEach()

对于第二段代码stream().map(item->item).forEach(System.out::println)他会调用ReferencePipeline 中的forEach()

原因:java8中对于Stream操作分为几个阶段:流源,中间操作,终止操作。

list.stream().forEach(System.out::println);:流源+终止操作。而Head中的foreach()方法对于流源遍历做了优化。

stream().map(item->item).forEach(System.out::println):map()操作是一个中间操作。对于有中间操作的流来说forEach()需要关注每个中间操作都做了什么,所以调用的是ReferencePipeline 中的forEach()

上一篇下一篇

猜你喜欢

热点阅读