持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
Stream的底层是怎么实现的
下面我们通过简单的示例来简单看看是怎么实现的:
/**
* 筛选并统计信息
*
* @param list
* @return
*/
private static long filterAndCount(List<Integer> list) {
return list.stream().filter(i -> i % 2 == 0).count();
}
流的创建
时序图比较简单,最后一步RefrencePipeline构造比较关键。Head是RefrencePipeline的子类,可以理解为Head是流水线的第一个stage。
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;
}
这里主要是存储了sourceSpliterator(这里为ArrayList$ArrayListSpliterator)。
中间操作
public final Stream<P_OUT> filter(Predicate<? super P_OUT> predicate) {
// 判断给定的predicate是否为空
Objects.requireNonNull(predicate);
return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SIZED) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
@Override
public void begin(long size) {
//重置Sink状态(不确定数据大小)
downstream.begin(-1);
}
@Override
public void accept(P_OUT u) {
//如果匹配就接收这个元素
if (predicate.test(u))
downstream.accept(u);
}
};
}
};
}
这里创建了一个StatelessOp(无状态操作,元素的处理不受之前元素的影响)继承了ReferencePipeline,构造的时候把this传进去了,实现了opWrapSink方法(接收了一个Sink又返回了一个Sink)。
具体调用等末端操作再看。
Sink
Consumer的一个扩展,用于在流管道的各个阶段执行值,并使用其他方法来管理大小信息、流控制等。在首次对Slink调用accept()方法之前,必须调用begin()方法来通知它数据即将到来(可选地通知接收器有多少数据即将到来),并且在发送所有数据之后,必须调用end()方法。在调用end()之后,不应该在neuter再次调用begin()的情况下调用accept()。Sink还提供了一种机制,通过该机制,接收器可以协同发送信号,表示它不希望接收更多的数据(cancellationRequested()方法),源可以在接收器发送更多数据之前轮询该方法。
RefrencePieline最终会将整个Stream流操作组装成一个调用链,而这条调用链上的各个Stream操作的上下关系就是通过Sink接口协议来定义实现的。
末端操作
末端操作能看出Stream底层是怎么实现的、惰性执行是怎么实现的
- ReferencePieline#mapToLong
@Override
public final LongStream mapToLong(ToLongFunction<? super P_OUT> mapper) {
Objects.requireNonNull(mapper);
return new LongPipeline.StatelessOp<P_OUT>(this, StreamShape.REFERENCE,
StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<Long> sink) {
return new Sink.ChainedReference<P_OUT, Long>(sink) {
@Override
public void accept(P_OUT u) {
downstream.accept(mapper.applyAsLong(u));
}
};
}
};
}
在count之前会把元素映射成1L,也是使用Sink来实现。
- ReduceOps#makeLong
public static TerminalOp<Long, Long>
makeLong(long identity, LongBinaryOperator operator) {
Objects.requireNonNull(operator);
class ReducingSink
implements AccumulatingSink<Long, Long, ReducingSink>, Sink.OfLong {
private long state;
@Override
public void begin(long size) {
//初始值赋值
state = identity;
}
@Override
public void accept(long t) {
//进行累加
state = operator.applyAsLong(state, t);
}
@Override
public Long get() {
return state;
}
@Override
public void combine(ReducingSink other) {
accept(other.state);
}
}
return new ReduceOp<Long, Long, ReducingSink>(StreamShape.LONG_VALUE) {
@Override
public ReducingSink makeSink() {
return new ReducingSink();
}
};
}
- AbstractPieline#wrapSink
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.pre
sink = p.opWrapSink(p.previousStage.combinedFlags, sink);
}
return (Sink<P_IN>) sink;
}
Pipeline也是链式结构,遍历包装成sink并返回,返回的是Sink.ChainedReference(本身也是个sink)实例,是一个链式结构,从外到内(从第一个中间操作到最后一个末端操作)。
- AbstractPieline#copyInto
final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) {
Objects.requireNonNull(wrappedSink);
if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) {
// 重置sink状态以接收新的数据集
wrappedSink.begin(spliterator.getExactSizeIfKnown());
// 进行遍历,这里依次调用filter->count
spliterator.forEachRemaining(wrappedSink);
wrappedSink.end();
}
else {
copyIntoWithCancel(wrappedSink, spliterator);
}
}