java8新特性-引用流-findAny,findFirst

java8新特性-引用流-findAny,findFirstStream的执行流程参考https://www.cnblogs.com/shigongp/p/17181380.html。findAny和findFirst都是从Stream中查找一个元素。它们的不同在于findAny不注重顺序,findFirst注重顺序。例子:List<User&g

大家好,欢迎来到IT知识分享网。

Stream的执行流程参考https://www.cnblogs.com/shigongp/p/17181380.html。
 
findAny和findFirst都是从Stream中查找一个元素。它们的不同在于findAny不注重顺序,findFirst注重顺序。

 

例子:

 List<User> users = new ArrayList<>();
 users.add(new User("张三",30));
 users.add(new User("李四",34));
 users.add(new User("王五",20));


 ptional<User> any = users.stream().findAny();
 System.out.println(any.get());

 Optional<User> first = users.stream().findFirst();
 System.out.println(first.get());

运行结果:

java8新特性-引用流-findAny,findFirst

 

源码分析:

 

ReferencePipeline#findAny()

 @Override
public final Optional<P_OUT> findAny() {
    return evaluate(FindOps.makeRef(false));
}

主要看FindOps.makeRef。

FindOps#makeRef

  public static <T> TerminalOp<T, Optional<T>> makeRef(boolean mustFindFirst) {
    return new FindOp<>(mustFindFirst, StreamShape.REFERENCE, Optional.empty(),
                        Optional::isPresent, FindSink.OfRef::new);
}


   FindOp(boolean mustFindFirst,
                   StreamShape shape,
                   O emptyValue,
                   Predicate<O> presentPredicate,
                   Supplier<TerminalSink<T, O>> sinkSupplier) {
        this.mustFindFirst = mustFindFirst;
        this.shape = shape;
        this.emptyValue = emptyValue;
        this.presentPredicate = presentPredicate;
        this.sinkSupplier = sinkSupplier;
    }

从FindOp构造函数看到findAny操作的Sink由sinkSupplier提供,即FindSink.OfRef。

从OfRef定义中看到,OfRef继承FindSink:

  static final class OfRef<T> extends FindSink<T, Optional<T>> {
        @Override
        public Optional<T> get() {
            return hasValue ? Optional.of(value) : null;
        }
    }

现在看看FindSink:

private static abstract class FindSink<T, O> implements TerminalSink<T, O> {
    boolean hasValue;
    T value;

    FindSink() {} // Avoid creation of special accessor

    @Override
    public void accept(T value) {
        if (!hasValue) {
            hasValue = true;
            this.value = value;
        }
    }

    @Override
    public boolean cancellationRequested() {
        return hasValue;
    }

    /** Specialization of {@code FindSink} for reference streams */
    static final class OfRef<T> extends FindSink<T, Optional<T>> {
        @Override
        public Optional<T> get() {
            return hasValue ? Optional.of(value) : null;
        }
    }

    /** Specialization of {@code FindSink} for int streams */
    static final class OfInt extends FindSink<Integer, OptionalInt>
            implements Sink.OfInt {
        @Override
        public void accept(int value) {
            // Boxing is OK here, since few values will actually flow into the sink
            accept((Integer) value);
        }

        @Override
        public OptionalInt get() {
            return hasValue ? OptionalInt.of(value) : null;
        }
    }

    /** Specialization of {@code FindSink} for long streams */
    static final class OfLong extends FindSink<Long, OptionalLong>
            implements Sink.OfLong {
        @Override
        public void accept(long value) {
            // Boxing is OK here, since few values will actually flow into the sink
            accept((Long) value);
        }

        @Override
        public OptionalLong get() {
            return hasValue ? OptionalLong.of(value) : null;
        }
    }

    /** Specialization of {@code FindSink} for double streams */
    static final class OfDouble extends FindSink<Double, OptionalDouble>
            implements Sink.OfDouble {
        @Override
        public void accept(double value) {
            // Boxing is OK here, since few values will actually flow into the sink
            accept((Double) value);
        }

        @Override
        public OptionalDouble get() {
            return hasValue ? OptionalDouble.of(value) : null;
        }
    }
}

主要看accept方法。hasValue默认是false。如果hasValue为false,则将value设置到FindSink的value中,同时将hasValue设置为true。

 
 
 

findAny和findFirst不同在于:

 public final Optional<P_OUT> findAny() {
    return evaluate(FindOps.makeRef(false));
}

 @Override
public final Optional<P_OUT> findFirst() {
    return evaluate(FindOps.makeRef(true));
}

传入的标志不一样。通过FindOps.makeRef构造函数传入的标志位最终设置到FindOp的mustFindFirst字段中。

FindOp#getOpFlags()

    @Override
    public int getOpFlags() {
        return StreamOpFlag.IS_SHORT_CIRCUIT | (mustFindFirst ? 0 : StreamOpFlag.NOT_ORDERED);
    }

mustFindFirst影响了Stream的操作特征。mustFindFirst为false表示Stream有NOT_ORDERED特征,不注重元素顺序。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/27580.html

(0)
上一篇 2023-12-05 20:33
下一篇 2023-12-06 08:45

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信