/** * Collect the elements output from the pipeline stage. * * @param generator the array generator to be used to create array instances * @return a flat array-backed Node that holds the collected output elements */ @SuppressWarnings("unchecked") final Node<E_OUT> evaluateToArrayNode(IntFunction<E_OUT[]> generator) { if (linkedOrConsumed) { throw new IllegalStateException(MSG_STREAM_LINKED); } linkedOrConsumed = true; // If the last intermediate operation is stateful then // evaluate directly to avoid an extra collection step if (isParallel() && previousStage != null && opIsStateful()) { // Set the depth of this, last, pipeline stage to zero to slice the // pipeline such that this operation will not be included in the // upstream slice and upstream operations will not be included // in this slice depth = 0; return opEvaluateParallel(previousStage, previousStage.sourceSpliterator(0), generator); } else { return evaluate(sourceSpliterator(0), true, generator); } }
@Override final <P_IN> Node<E_OUT> evaluate(Spliterator<P_IN> spliterator, boolean flatten, IntFunction<E_OUT[]> generator) { if (isParallel()) { // @@@ Optimize if op of this pipeline stage is a stateful op return evaluateToNode(this, spliterator, flatten, generator); } else { Node.Builder<E_OUT> nb = makeNodeBuilder( exactOutputSizeIfKnown(spliterator), generator); return wrapAndCopyInto(nb, spliterator).build(); } }
@Override @SuppressWarnings("unchecked") final <P_IN> Spliterator<E_OUT> wrapSpliterator(Spliterator<P_IN> sourceSpliterator) { if (depth == 0) { return (Spliterator<E_OUT>) sourceSpliterator; } else { return wrap(this, () -> sourceSpliterator, isParallel()); } }
@Override @SuppressWarnings("unchecked") public Spliterator<E_OUT> spliterator() { if (linkedOrConsumed) throw new IllegalStateException(MSG_STREAM_LINKED); linkedOrConsumed = true; if (this == sourceStage) { if (sourceStage.sourceSpliterator != null) { Spliterator<E_OUT> s = (Spliterator<E_OUT>) sourceStage.sourceSpliterator; sourceStage.sourceSpliterator = null; return s; } else if (sourceStage.sourceSupplier != null) { Supplier<Spliterator<E_OUT>> s = (Supplier<Spliterator<E_OUT>>) sourceStage.sourceSupplier; sourceStage.sourceSupplier = null; return lazySpliterator(s); } else { throw new IllegalStateException(MSG_CONSUMED); } } else { return wrap(this, () -> sourceSpliterator(0), isParallel()); } }
@Override protected final Node<P_OUT> doLeaf() { if (isRoot()) { long sizeIfKnown = StreamOpFlag.SIZED.isPreserved(op.sourceOrOpFlags) ? op.exactOutputSizeIfKnown(spliterator) : -1L; Node.Builder<P_OUT> nb = op.makeNodeBuilder(sizeIfKnown, generator); Sink<P_OUT> opSink = op.opWrapSink(helper.getStreamAndOpFlags(), nb); helper.copyIntoWithCancel(helper.wrapSink(opSink), spliterator); // There is no need to truncate since the op performs the // skipping and limiting of elements return nb.build(); } else { Node.Builder<P_OUT> nb = op.makeNodeBuilder(-1, generator); if (targetOffset == 0) { // limit only Sink<P_OUT> opSink = op.opWrapSink(helper.getStreamAndOpFlags(), nb); helper.copyIntoWithCancel(helper.wrapSink(opSink), spliterator); } else { helper.wrapAndCopyInto(nb, spliterator); } Node<P_OUT> node = nb.build(); thisNodeSize = node.count(); completed = true; spliterator = null; return node; } }
if (isParallel() && sourceStage.sourceAnyStateful) { if (p.opIsStateful()) { depth = 0; spliterator = p.opEvaluateParallelLazy(u, spliterator);
@Override final StreamShape getSourceShape() { @SuppressWarnings("rawtypes") AbstractPipeline p = AbstractPipeline.this; while (p.depth > 0) { p = p.previousStage; } return p.getOutputShape(); }
@Override final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) { Objects.requireNonNull(wrappedSink); if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) { wrappedSink.begin(spliterator.getExactSizeIfKnown()); spliterator.forEachRemaining(wrappedSink); wrappedSink.end(); } else { copyIntoWithCancel(wrappedSink, spliterator); } }
/** * Evaluate the pipeline with a terminal operation to produce a result. * * @param <R> the type of result * @param terminalOp the terminal operation to be applied to the pipeline. * @return the result */ final <R> R evaluate(TerminalOp<E_OUT, R> terminalOp) { if (linkedOrConsumed) throw new IllegalStateException(MSG_STREAM_LINKED); linkedOrConsumed = true; return isParallel() ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags())) : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags())); }
@Override final <P_IN> long exactOutputSizeIfKnown(Spliterator<P_IN> spliterator) { return StreamOpFlag.SIZED.isKnown(getStreamAndOpFlags()) ? spliterator.getExactSizeIfKnown() : -1L; }
@Override @SuppressWarnings("unchecked") final <P_IN> boolean copyIntoWithCancel(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) { @SuppressWarnings("rawtypes") AbstractPipeline p = AbstractPipeline.this; while (p.depth > 0) { p = p.previousStage; } wrappedSink.begin(spliterator.getExactSizeIfKnown()); boolean cancelled = p.forEachWithCancel(spliterator, wrappedSink); wrappedSink.end(); return cancelled; }
@Override protected final Node<P_OUT> doLeaf() { boolean isChild = !isRoot(); // If this not the root and pipeline is ordered and size is known // then pre-size the builder long sizeIfKnown = isChild && isOrdered && StreamOpFlag.SIZED.isPreserved(op.sourceOrOpFlags) ? op.exactOutputSizeIfKnown(spliterator) : -1; Node.Builder<P_OUT> builder = helper.makeNodeBuilder(sizeIfKnown, generator); @SuppressWarnings("unchecked") DropWhileOp<P_OUT> dropOp = (DropWhileOp<P_OUT>) op; // If this leaf is the root then there is no merging on completion // and there is no need to retain dropped elements DropWhileSink<P_OUT> s = dropOp.opWrapSink(builder, isOrdered && isChild); helper.wrapAndCopyInto(s, spliterator); Node<P_OUT> node = builder.build(); thisNodeSize = node.count(); index = s.getDropCount(); return node; }
@Override @SuppressWarnings("unchecked") public Spliterator<E_OUT> spliterator() { if (linkedOrConsumed) throw new IllegalStateException(MSG_STREAM_LINKED); linkedOrConsumed = true; if (this == sourceStage) { if (sourceStage.sourceSpliterator != null) { Spliterator<E_OUT> s = (Spliterator<E_OUT>) sourceStage.sourceSpliterator; sourceStage.sourceSpliterator = null; return s; } else if (sourceStage.sourceSupplier != null) { Supplier<Spliterator<E_OUT>> s = (Supplier<Spliterator<E_OUT>>) sourceStage.sourceSupplier; sourceStage.sourceSupplier = null; return lazySpliterator(s); } else { throw new IllegalStateException(MSG_CONSUMED); } } else { return wrap(this, () -> sourceSpliterator(0), isParallel()); } }
@Override protected final Node<P_OUT> doLeaf() { if (isRoot()) { long sizeIfKnown = StreamOpFlag.SIZED.isPreserved(op.sourceOrOpFlags) ? op.exactOutputSizeIfKnown(spliterator) : -1L; Node.Builder<P_OUT> nb = op.makeNodeBuilder(sizeIfKnown, generator); Sink<P_OUT> opSink = op.opWrapSink(helper.getStreamAndOpFlags(), nb); helper.copyIntoWithCancel(helper.wrapSink(opSink), spliterator); // There is no need to truncate since the op performs the // skipping and limiting of elements return nb.build(); } else { Node.Builder<P_OUT> nb = op.makeNodeBuilder(-1, generator); if (targetOffset == 0) { // limit only Sink<P_OUT> opSink = op.opWrapSink(helper.getStreamAndOpFlags(), nb); helper.copyIntoWithCancel(helper.wrapSink(opSink), spliterator); } else { helper.wrapAndCopyInto(nb, spliterator); } Node<P_OUT> node = nb.build(); thisNodeSize = node.count(); completed = true; spliterator = null; return node; } }
if (isParallel() && sourceStage.sourceAnyStateful) { if (p.opIsStateful()) { depth = 0; spliterator = p.opEvaluateParallelLazy(u, spliterator);
@Override final StreamShape getSourceShape() { @SuppressWarnings("rawtypes") AbstractPipeline p = AbstractPipeline.this; while (p.depth > 0) { p = p.previousStage; } return p.getOutputShape(); }
@Override final <P_IN> void copyInto(Sink<P_IN> wrappedSink, Spliterator<P_IN> spliterator) { Objects.requireNonNull(wrappedSink); if (!StreamOpFlag.SHORT_CIRCUIT.isKnown(getStreamAndOpFlags())) { wrappedSink.begin(spliterator.getExactSizeIfKnown()); spliterator.forEachRemaining(wrappedSink); wrappedSink.end(); } else { copyIntoWithCancel(wrappedSink, spliterator); } }
@Override @SuppressWarnings("unchecked") final <P_IN> Spliterator<E_OUT> wrapSpliterator(Spliterator<P_IN> sourceSpliterator) { if (depth == 0) { return (Spliterator<E_OUT>) sourceSpliterator; } else { return wrap(this, () -> sourceSpliterator, isParallel()); } }
/** * Evaluate the pipeline with a terminal operation to produce a result. * * @param <R> the type of result * @param terminalOp the terminal operation to be applied to the pipeline. * @return the result */ final <R> R evaluate(TerminalOp<E_OUT, R> terminalOp) { if (linkedOrConsumed) throw new IllegalStateException(MSG_STREAM_LINKED); linkedOrConsumed = true; return isParallel() ? terminalOp.evaluateParallel(this, sourceSpliterator(terminalOp.getOpFlags())) : terminalOp.evaluateSequential(this, sourceSpliterator(terminalOp.getOpFlags())); }