Stream的操作

中间操作

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();
}

 

转载于:https://www.cnblogs.com/flying-snake/p/11537996.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值