中间操作
map()
返回一个流,当中包含了将给定函数应用到当前流中的每一个元素后返回的结果。
只有一种实现,在 ReferencePipeline 中定义
创建一个 StatelessOp(ReferencePipeline 的内部类),重写 opWrapSink(定义在 AbstractPipeline 中) 方法后返回
opWrapSink 方法创建 Sink.ChainedReference,重写 accept 方法,并返回
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)); } }; } }; }
终止操作
forEach()
此操作的行为是非确定的;对于并行流,此操作并不会遵循遇到的元素的顺序,否则,将会牺牲掉并行的优势;对于任意的元素,此动作可能会在任意的时间、库提供的任意的线程中执行;若此动作访问了共享的状态,则需要提供必要的同步机制
实现
1. ReferencePipeline.Head.forEach()
当stream()与forEach()之间无中间操作时,由于 stream() 构建时,创建的是 ReferencePipeline.Head,并且重写了 forEach 方法,因此调用的是 ReferencePipeline.Head 中的方法,直接对源进行遍历
@Override public void forEach(Consumer<? super E_OUT> action) { if (!isParallel()) { sourceStageSpliterator().forEachRemaining(action); } else { super.forEach(action); } }
以非并行为例
调用的是 Spliterator 接口的 tryAdvance 方法
通过 while 循环不断执行 tryAdvance 方法,直至遍历完成返回 false
相当于将 Iterator 的 hasNext() 与 next() 方法合并
default void forEachRemaining(Consumer<? super T> action) { do { } while (tryAdvance(action)); }
tryAdvance有众多实现类,以 ArrayList 中的 ArrayListSpliterator 中的实现为例
将 Spliterator 中的下一个元素取出后,执行 action.accept();若到达结尾处,返回false
private int getFence() { // initialize fence to size on first use
int hi; // (a specialized variant appears in method forEach)
ArrayList<E> lst;
if ((hi = fence) < 0) {
if ((lst = list) == null)
hi = fence = 0;
else {
expectedModCount = lst.modCount;
hi = fence = lst.size;
}
}
return hi;
}
public boolean tryAdvance(Consumer<? super E> action) { if (action == null) throw new NullPointerException(); int hi = getFence(), i = index; if (i < hi) { index = i + 1; @SuppressWarnings("unchecked") E e = (E)list.elementData[i]; action.accept(e); if (list.modCount != expectedModCount) throw new ConcurrentModificationException(); return true; } return false; }
2. ReferencePipeline.forEach()
当存在中间操作时,每添加一个操作,都会创建一个 ReferencePipeline.StatelessOp 对象,由于 StatelessOp 没有重写 forEach 方法,因此,调用的是 ReferencePipeline 中的方法
@Override public void forEach(Consumer<? super P_OUT> action) { evaluate(ForEachOps.makeRef(action, false)); }
final <R> R evaluate(TerminalOp<E_OUT, R> terminalOp) { assert getOutputShape() == terminalOp.inputShape(); if (linkedOrConsumed) throw new IllegalStateException(MSG_STREAM_LINKED); linkedOrConsumed = true; return isParallel() ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags())) : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags())); }
sourceSpliterator() 方法用于获取当前管道阶段的源 spliterator
以串行流为例
@Override public <S> Void evaluateSequential(PipelineHelper<T> helper, Spliterator<S> spliterator) { return helper.wrapAndCopyInto(this, spliterator).get(); }