/** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************/package java.util.stream;import java.util.Optional;import java.util.OptionalDouble;import java.util.OptionalInt;import java.util.OptionalLong;import java.util.Spliterator;import java.util.concurrent.CountedCompleter;import java.util.function.Predicate;import java.util.function.Supplier;/*** Factory for instances of a short-circuiting {@code TerminalOp} that searches* for an element in a stream pipeline, and terminates when it finds one.* Supported variants include find-first (find the first element in the* encounter order) and find-any (find any element, may not be the first in* encounter order.)** @since 1.8*/final class FindOps {private FindOps() { }/*** Constructs a {@code TerminalOp} for streams of objects.** @param <T> the type of elements of the stream* @param mustFindFirst whether the {@code TerminalOp} must produce the* first element in the encounter order* @return a {@code TerminalOp} implementing the find operation*/@SuppressWarnings("unchecked")public static <T> TerminalOp<T, Optional<T>> makeRef(boolean mustFindFirst) {return (TerminalOp<T, Optional<T>>)(mustFindFirst ? FindSink.OfRef.OP_FIND_FIRST : FindSink.OfRef.OP_FIND_ANY);}/*** Constructs a {@code TerminalOp} for streams of ints.** @param mustFindFirst whether the {@code TerminalOp} must produce the* first element in the encounter order* @return a {@code TerminalOp} implementing the find operation*/public static TerminalOp<Integer, OptionalInt> makeInt(boolean mustFindFirst) {return mustFindFirst ? FindSink.OfInt.OP_FIND_FIRST : FindSink.OfInt.OP_FIND_ANY;}/*** Constructs a {@code TerminalOp} for streams of longs.** @param mustFindFirst whether the {@code TerminalOp} must produce the* first element in the encounter order* @return a {@code TerminalOp} implementing the find operation*/public static TerminalOp<Long, OptionalLong> makeLong(boolean mustFindFirst) {return mustFindFirst ? FindSink.OfLong.OP_FIND_FIRST : FindSink.OfLong.OP_FIND_ANY;}/*** Constructs a {@code FindOp} for streams of doubles.** @param mustFindFirst whether the {@code TerminalOp} must produce the* first element in the encounter order* @return a {@code TerminalOp} implementing the find operation*/public static TerminalOp<Double, OptionalDouble> makeDouble(boolean mustFindFirst) {return mustFindFirst ? FindSink.OfDouble.OP_FIND_FIRST : FindSink.OfDouble.OP_FIND_ANY;}/*** A short-circuiting {@code TerminalOp} that searches for an element in a* stream pipeline, and terminates when it finds one. Implements both* find-first (find the first element in the encounter order) and find-any* (find any element, may not be the first in encounter order.)** @param <T> the output type of the stream pipeline* @param <O> the result type of the find operation, typically an optional* type*/private static final class FindOp<T, O> implements TerminalOp<T, O> {private final StreamShape shape;final int opFlags;final O emptyValue;final Predicate<O> presentPredicate;final Supplier<TerminalSink<T, O>> sinkSupplier;/*** Constructs a {@code FindOp}.** @param mustFindFirst if true, must find the first element in* encounter order, otherwise can find any element* @param shape stream shape of elements to search* @param emptyValue result value corresponding to "found nothing"* @param presentPredicate {@code Predicate} on result value* corresponding to "found something"* @param sinkSupplier supplier for a {@code TerminalSink} implementing* the matching functionality*/FindOp(boolean mustFindFirst,StreamShape shape,O emptyValue,Predicate<O> presentPredicate,Supplier<TerminalSink<T, O>> sinkSupplier) {this.opFlags = StreamOpFlag.IS_SHORT_CIRCUIT | (mustFindFirst ? 0 : StreamOpFlag.NOT_ORDERED);this.shape = shape;this.emptyValue = emptyValue;this.presentPredicate = presentPredicate;this.sinkSupplier = sinkSupplier;}@Overridepublic int getOpFlags() {return opFlags;}@Overridepublic StreamShape inputShape() {return shape;}@Overridepublic <S> O evaluateSequential(PipelineHelper<T> helper,Spliterator<S> spliterator) {O result = helper.wrapAndCopyInto(sinkSupplier.get(), spliterator).get();return result != null ? result : emptyValue;}@Overridepublic <P_IN> O evaluateParallel(PipelineHelper<T> helper,Spliterator<P_IN> spliterator) {// This takes into account the upstream ops flags and the terminal// op flags and therefore takes into account findFirst or findAnyboolean mustFindFirst = StreamOpFlag.ORDERED.isKnown(helper.getStreamAndOpFlags());return new FindTask<>(this, mustFindFirst, helper, spliterator).invoke();}}/*** Implementation of @{code TerminalSink} that implements the find* functionality, requesting cancellation when something has been found** @param <T> The type of input element* @param <O> The result type, typically an optional type*/private abstract static class FindSink<T, O> implements TerminalSink<T, O> {boolean hasValue;T value;FindSink() {} // Avoid creation of special accessor@Overridepublic void accept(T value) {if (!hasValue) {hasValue = true;this.value = value;}}@Overridepublic boolean cancellationRequested() {return hasValue;}/** Specialization of {@code FindSink} for reference streams */static final class OfRef<T> extends FindSink<T, Optional<T>> {@Overridepublic Optional<T> get() {return hasValue ? Optional.of(value) : null;}static final TerminalOp<?, ?> OP_FIND_FIRST = new FindOp<>(true,StreamShape.REFERENCE, Optional.empty(),Optional::isPresent, FindSink.OfRef::new);static final TerminalOp<?, ?> OP_FIND_ANY = new FindOp<>(false,StreamShape.REFERENCE, Optional.empty(),Optional::isPresent, FindSink.OfRef::new);}/** Specialization of {@code FindSink} for int streams */static final class OfInt extends FindSink<Integer, OptionalInt>implements Sink.OfInt {@Overridepublic void accept(int value) {// Boxing is OK here, since few values will actually flow into the sinkaccept((Integer) value);}@Overridepublic OptionalInt get() {return hasValue ? OptionalInt.of(value) : null;}static final TerminalOp<Integer, OptionalInt> OP_FIND_FIRST = new FindOp<>(true,StreamShape.INT_VALUE, OptionalInt.empty(),OptionalInt::isPresent, FindSink.OfInt::new);static final TerminalOp<Integer, OptionalInt> OP_FIND_ANY = new FindOp<>(false,StreamShape.INT_VALUE, OptionalInt.empty(),OptionalInt::isPresent, FindSink.OfInt::new);}/** Specialization of {@code FindSink} for long streams */static final class OfLong extends FindSink<Long, OptionalLong>implements Sink.OfLong {@Overridepublic void accept(long value) {// Boxing is OK here, since few values will actually flow into the sinkaccept((Long) value);}@Overridepublic OptionalLong get() {return hasValue ? OptionalLong.of(value) : null;}static final TerminalOp<Long, OptionalLong> OP_FIND_FIRST = new FindOp<>(true,StreamShape.LONG_VALUE, OptionalLong.empty(),OptionalLong::isPresent, FindSink.OfLong::new);static final TerminalOp<Long, OptionalLong> OP_FIND_ANY = new FindOp<>(false,StreamShape.LONG_VALUE, OptionalLong.empty(),OptionalLong::isPresent, FindSink.OfLong::new);}/** Specialization of {@code FindSink} for double streams */static final class OfDouble extends FindSink<Double, OptionalDouble>implements Sink.OfDouble {@Overridepublic void accept(double value) {// Boxing is OK here, since few values will actually flow into the sinkaccept((Double) value);}@Overridepublic OptionalDouble get() {return hasValue ? OptionalDouble.of(value) : null;}static final TerminalOp<Double, OptionalDouble> OP_FIND_FIRST = new FindOp<>(true,StreamShape.DOUBLE_VALUE, OptionalDouble.empty(),OptionalDouble::isPresent, FindSink.OfDouble::new);static final TerminalOp<Double, OptionalDouble> OP_FIND_ANY = new FindOp<>(false,StreamShape.DOUBLE_VALUE, OptionalDouble.empty(),OptionalDouble::isPresent, FindSink.OfDouble::new);}}/*** {@code ForkJoinTask} implementing parallel short-circuiting search* @param <P_IN> Input element type to the stream pipeline* @param <P_OUT> Output element type from the stream pipeline* @param <O> Result type from the find operation*/@SuppressWarnings("serial")private static final class FindTask<P_IN, P_OUT, O>extends AbstractShortCircuitTask<P_IN, P_OUT, O, FindTask<P_IN, P_OUT, O>> {private final FindOp<P_OUT, O> op;private final boolean mustFindFirst;FindTask(FindOp<P_OUT, O> op,boolean mustFindFirst,PipelineHelper<P_OUT> helper,Spliterator<P_IN> spliterator) {super(helper, spliterator);this.mustFindFirst = mustFindFirst;this.op = op;}FindTask(FindTask<P_IN, P_OUT, O> parent, Spliterator<P_IN> spliterator) {super(parent, spliterator);this.mustFindFirst = parent.mustFindFirst;this.op = parent.op;}@Overrideprotected FindTask<P_IN, P_OUT, O> makeChild(Spliterator<P_IN> spliterator) {return new FindTask<>(this, spliterator);}@Overrideprotected O getEmptyResult() {return op.emptyValue;}private void foundResult(O answer) {if (isLeftmostNode())shortCircuit(answer);elsecancelLaterNodes();}@Overrideprotected O doLeaf() {O result = helper.wrapAndCopyInto(op.sinkSupplier.get(), spliterator).get();if (!mustFindFirst) {if (result != null)shortCircuit(result);return null;}else {if (result != null) {foundResult(result);return result;}elsereturn null;}}@Overridepublic void onCompletion(CountedCompleter<?> caller) {if (mustFindFirst) {for (FindTask<P_IN, P_OUT, O> child = leftChild, p = null; child != p;p = child, child = rightChild) {O result = child.getLocalResult();if (result != null && op.presentPredicate.test(result)) {setLocalResult(result);foundResult(result);break;}}}super.onCompletion(caller);}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。