java中StreamAPI的流的创建及操作原理分析

前言

StreamAPI是java8提供的一种方便,高效操作容器的工具。可以根据数组或集合创建一个流。

简单使用

import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Client {

  public static void main(String[] args) {
    //根据int数组创建流
    System.out.println(Arrays.stream(new int[]{1, 2, 3, 4, 5}).sum());
    //根据对象数组创建流
    System.out.println(Stream.of("a", "b", "c").collect(Collectors.joining(",")));
    //创建无限流
    System.out.println(Stream.generate(() -> 1).limit(5).mapToInt(x -> x).sum());
  }

}

一个Stream流有3部分构成

  • 零个或多个中间操作
  • 终止操作

无状态表示当前元素的处理不受之前元素的影响,有状态表示只有拿到所有元素才能处理,如排序。

/**
* 分割迭代器接口,核心接口
*/
public interface Spliterator<T> {
    /**
     * 如果还有剩余元素,执行action,返回true,否则返回false,相当于迭代器的hasNext()和next()的结合
     */
    boolean tryAdvance(Consumer<? super T> action);

    /**
     * 对所有剩余元素执行action
     */
    default void forEachRemaining(Consumer<? super T> action) {
        do { } while (tryAdvance(action));
    }

    /**
     * 将一个Spliterator按大小分割成左右两个Spliterator,并行流调用
     */
    Spliterator<T> trySplit();

    /**
     * 返回一个估计的大小
     */
    long estimateSize();

    /**
     * 如果知道大小,返回确切大小
     */
    default long getExactSizeIfKnown() {
        return (characteristics() & SIZED) == 0 ? -1L : estimateSize();
    }

    /**
     * 返回分割器的标识
     */
    int characteristics();

    /**
     * 是否包含指定标识
     */
    default boolean hasCharacteristics(int characteristics) {
        return (characteristics() & characteristics) == characteristics;
    }

    /**
     * 返回比较器
     */
    default Comparator<? super T> getComparator() {
        throw new IllegalStateException();
    }

    /**
     * 是否有序
     */
    public static final int ORDERED    = 0x00000010;

    /**
     * 是否去重
     */
    public static final int DISTINCT   = 0x00000001;

    /**
     * 排序的
     */
    public static final int SORTED     = 0x00000004;

    /**
     * 有确定大小的
     */
    public static final int SIZED      = 0x00000040;

    /**
     * 非空的
     */
    public static final int NONNULL    = 0x00000100;

    /**
     * 不可变的
     */
    public static final int IMMUTABLE  = 0x00000400;

    /**
     * 支持并发的
     */
    public static final int CONCURRENT = 0x00001000;

    /**
     * 分割后确定大小的
     */
    public static final int SUBSIZED = 0x00004000;

}

关于Spliterator接口的子接口OfInt的一个疑惑

/**
     * A Spliterator specialized for {@code int} values.
     * @since 1.8
     */
    public interface OfInt extends OfPrimitive<Integer, IntConsumer, OfInt> {

        @Override
        OfInt trySplit();

        @Override
        boolean tryAdvance(IntConsumer action);

        /**
         * {@inheritDoc}
         * @implSpec
         * If the action is an instance of {@code IntConsumer} then it is cast
         * to {@code IntConsumer} and passed to
         * {@link #tryAdvance(java.util.function.IntConsumer)}; otherwise
         * the action is adapted to an instance of {@code IntConsumer}, by
         * boxing the argument of {@code IntConsumer}, and then passed to
         * {@link #tryAdvance(java.util.function.IntConsumer)}.
         */
        @Override
        default boolean tryAdvance(Consumer<? super Integer> action) {
            if (action instanceof IntConsumer) {
                return tryAdvance((IntConsumer) action);
            }
            else {
                if (Tripwire.ENABLED)
                    Tripwire.trip(getClass(),
                                  "{0} calling Spliterator.OfInt.tryAdvance((IntConsumer) action::accept)");
                return tryAdvance((IntConsumer) action::accept);
            }
        }
    }

有两个tryAdvance的重载方法,一个参数类型为IntConsumer ,一个参数类型为Consumer,Consumer 和 IntConsumer 接口之间是没有任何的继承关系的,为什么能够强转成功,不知道传递什么参数会达到这一步。

/**
     * A Spliterator using a given Iterator for element
     * operations. The spliterator implements {@code trySplit} to
     * permit limited parallelism.
     */
    static class IteratorSpliterator<T> implements Spliterator<T> {
        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            if (action == null) throw new NullPointerException();
            if (it == null) {
                it = collection.iterator();
                est = (long) collection.size();
            }
            if (it.hasNext()) {
                action.accept(it.next());
                return true;
            }
            return false;
        }
    }

集合容器使用的Spliterator ,基于Iterator 。tryAdvance()方法就是调用迭代器的hasNext()和next()方法。

源码分析

abstract class AbstractPipeline<E_IN, E_OUT, S extends BaseStream<E_OUT, S>>
        extends PipelineHelper<E_OUT> implements BaseStream<E_OUT, S> {

    /**
     * 管道的源阶段
     */
    @SuppressWarnings("rawtypes")
    private final AbstractPipeline sourceStage;

    /**
     * 管道的上一个阶段
     */
    @SuppressWarnings("rawtypes")
    private final AbstractPipeline previousStage;

    /**
     * The operation flags for the intermediate operation represented by this
     * pipeline object.
     */
    protected final int sourceOrOpFlags;

    /**
     * 管道的下一个阶段
     */
    @SuppressWarnings("rawtypes")
    private AbstractPipeline nextStage;

    /**
     * 深度
     */
    private int depth;

    /**
     * 源分割器
     */
    private Spliterator<?> sourceSpliterator;

}

一个管道流包括一个源头和多个中间阶段,通过类似双向链表的方式连接起来。

通过Sink接口将所有操作连接起来,相互调用。如Stream.map()将操作封装成一个Sink。

    @Override
    @SuppressWarnings("unchecked")
    public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
        Objects.requireNonNull(mapper);
        return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
                                     StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
            @Override
            Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
                return new Sink.ChainedReference<P_OUT, R>(sink) {
                    @Override
                    public void accept(P_OUT u) {
                        downstream.accept(mapper.apply(u));
                    }
                };
            }
        };
    }

从当前阶段向前找,直到源阶段,将最后一个Sink依次包装成一个包含所有操作的Sink

    @Override
    @SuppressWarnings("unchecked")
    final <P_IN> Sink<P_IN> wrapSink(Sink<E_OUT> sink) {
        Objects.requireNonNull(sink);

        for ( @SuppressWarnings("rawtypes") AbstractPipeline p=AbstractPipeline.this; p.depth > 0; p=p.previousStage) {
            sink = p.opWrapSink(p.previousStage.combinedFlags, sink);
        }
        return (Sink<P_IN>) sink;
    }

执行最终的Sink

    @Override
    final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) {
        Objects.requireNonNull(wrappedSink);

        if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) {
            wrappedSink.begin(spliterator.getExactSizeIfKnown());
            spliterator.forEachRemaining(wrappedSink);
            wrappedSink.end();
        }
        else {
            copyIntoWithCancel(wrappedSink, spliterator);
        }
    }

此时的Sink就是包含所有操作的Sink,执行这个Sink就是执行整个流。

参考

Java8之Stream API原理
深入理解Java Stream流水线
Weird implementation of tryAdvance in Spliterator.OfInt

posted @ 2021-04-14 09:18  strongmore  阅读(297)  评论(0编辑  收藏  举报