流操作可以分为中间操作和结束操作。
Stream的实现:
流式操作将每一步都对应一个Pipeline对象(Stage),其由三部分组成,即<数据源,操作,回调函数>。
Pipeline虽然知道自己这一步应该做什么,但是不知道下一步应该做什么,比如xxx.stream().map().filter().collect(),map()函数创造的StatelessOp虽然知道我自己应该做的是根据传入的回调函数做map操作,但是不知道下一步应该是fliter(),所以在此之上多了一层封装,即将每个Stage都封装成一个Sink对象,每个Sink统一接口,当map对象的Sink执行完逻辑后,只需要调用下一个Sink的accpet()方法即可。
以集合类为例,首先看Collection的stream()函数,这是流的起点。
//Collection接口
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
//StreamSupport
public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel) {
Objects.requireNonNull(spliterator);
return new ReferencePipeline.Head<>(spliterator,
StreamOpFlag.fromCharacteristics(spliterator),
parallel);
}
//可以看到创建了一个Head类,parallel参数判断是否是并行流
//此处先看单行流,spliterator是一个迭代器,即数据源
//为何使用迭代器呢?这是因为迭代器封装了数据遍历操作
//这样不管什么类型的数据,访问只需要调用统一的next()和hasNext()方法
最终调用了AbstractPipeline的构造方法:
AbstractPipeline(Spliterator<?> source,
int sourceFlags, boolean parallel) {
this.previousStage = null; //没有上游,流的起点
this.sourceSpliterator = source;//数据源
this.sourceStage = this;
this.sourceOrOpFlags = sourceFlags & StreamOpFlag.STREAM_MASK;
// The following is an optimization of:
// StreamOpFlag.combineOpFlags(sourceOrOpFlags, StreamOpFlag.INITIAL_OPS_VALUE);
this.combinedFlags = (~(sourceOrOpFlags << 1)) & StreamOpFlag.INITIAL_OPS_VALUE;
this.depth = 0;
this.parallel = parallel;
}
然后通过stream()方法得到一个Head对象,我们再调用Head()对象的map()方法,则又会返回一个新的StatelessOp对象,并且其previousStage指向Head。
因为Head是ReferencePipeline的子类,且没有重写map()、fliter()等等的方法,所有我们看ReferencePipeline的map()方法:
@Override
@SuppressWarnings("unchecked")
public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
Objects.requireNonNull(mapper);
//创建了一个新的StatelessOp对象,并返回了
return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
//该方法是核心,将Pipeline的逻辑封装为一个Sink并串连
@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));
}
};
}
};
}
这样不断的进行,就可以形成一个从下游到上游的单向链表。即:
Head<—StatelessOp(map)<—… <—TerminalOp(collect)
结束操作会通过ReduceOps、MatchOps等工具类的makeRef()方法构造一个TerminalOp。
前面流已经完成了从下至上的连接,但是还无法执行,因为是逆序的。
如何来完成从上游到下游的连接? 这一切从TerminalOp的evaluateSequential()开始。
当我们调用了结束方法(anyMatch、collect等等)后,会调用ReferencePipeline的evaluate(TerminalOp)方法,该方法会完成由上到下的连接。
evaluate方法会根据并行与否执行terminalOp.evaluateParallel或者terminalOp.evaluateSequential方法。
以evaluateSequential为例:该方法在不同的结束操作中有不同的实现,以ReduceOps(collect()底层使用该结束操作类)为例。
//此处helper为evaluateSequential()将this作为参数传入,
//因为terminalOp实现了PipelineHelper接口
@Override
public <P_IN> R evaluateSequential(PipelineHelper<T> helper,
Spliterator<P_IN> spliterator) {
return helper.wrapAndCopyInto(makeSink(), spliterator).get();
}
//而terminalOp实现的该接口是继承自父类AbstractPipeline
//所以最终wrapAndCopyInto是来自AbstractPipeline
//AbstractPipeline类
@Override
final <P_IN, S extends Sink<E_OUT>> S wrapAndCopyInto(S sink, Spliterator<P_IN> spliterator) {
copyInto(wrapSink(Objects.requireNonNull(sink)), spliterator);
return sink;
}
最终逻辑就定义在wrapSink函数中:
@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) {
//递归调用onWrapSink函数,将自己作为downstream参数传入
//p指向当前sink的previousStage,即upstream
sink = p.opWrapSink(p.previousStage.combinedFlags, sink);
}
return (Sink<P_IN>) sink;
}
//最后返回最顶层的Sink
这样就完成了由上游到下游的连接,调用的时候(copyInto()函数),我们看每个Sink的几个方法中,肯定会包含downstream.accept()的调用。这样就可以从Sink执行完毕后,将数据传入下一个Sink,进行接下来的处理。
注意数据源是在:
terminalOp.evaluateSequential(this,sourceSpliterator(terminalOp.getOpFlags()));作为参数传入的
//copyInto()函数
@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);
}
}
数据处理由spliterator.forEachRemaining(wrappedSink)语句完成。
//spliterator接口
default void forEachRemaining(Consumer<? super T> action) {
do { } while (tryAdvance(action));
}
//tryAdvance函数由具体实现类去实现
//这里,由于我们是使用容器Collection产生的流,
//所以spliterator的具体类型为IteratorSpliterator
//回顾前面Collection在调用stream()函数时,调用了一次spliterator()
//该函数调用Spliterators.spliterator(this, 0)生成一个IteratorSpliterator
由于Collection产生的流所对应的spliterator的具体实现类为IteratorSpliterator,我们看IteratorSpliterator的tryAdvance()方法:
@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()) {
//调用顶层Sink的accpet,然后由于每个Sink
//在accept函数中都明确调用downstream.accpet()
//因此完成了流式处理,最终返回结果
action.accept(it.next());
return true;
}
return false;
}