--- /dev/null 2013-02-14 00:07:37.184020992 -0500 +++ new/src/share/classes/java/util/stream/ForEachUntilOp.java 2013-02-21 14:11:05.000000000 -0500 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.util.stream; + +import java.util.Objects; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.IntConsumer; +import java.util.function.LongConsumer; + +/** + * A {@code TerminalOp} that evaluates a stream pipeline and sends the output into a {@code TerminalSink}, attempting + * to stop early if some external termination condition is reached. + * + * @apiNote + * The termination condition is an externally-imposed criteria, and is useful for problems like "find the best + * answer that can be found in ten seconds", "search until you find an answer at least as good as X", etc. It is not + * designed to provide content-based cancellation, such as "process elements until you find one which matches + * a given criteria." + * + *

There is no guarantee that additional elements will not be processed after the termination criteria has + * transpired. For example, a termination criteria of {@code resultSet.size() > TARGET} does not guarantee that the + * result set will receive no more than {@code TARGET} elements, but instead that @{code ForEachUntilOp} will attempt + * to stop after {@code TARGET} elements have been placed in the result set. + * + * @param The output type of the stream pipeline + * @since 1.8 + */ +class ForEachUntilOp extends ForEachOp implements TerminalOp { + public ForEachUntilOp(TerminalSink sink, StreamShape shape) { + super(sink, shape); + } + + /** + * Construct a {@code ForEachUntilOp} that reads from a {@code Stream} and sends the stream output to + * the provided {@code Consumer}, until the specified {@code BooleanProvider} indicates that no more input + * should be sent + * @param consumer The {@code Consumer} to send stream output to + * @param until A {@code BooleanSupplier} that indicates whether the termination criteria has occurred. Once + * it returns @{code true} the first time, it must continue to return {@code true} for all future + * invocations + * @param The type of the stream elements + */ + public static ForEachUntilOp make(final Consumer consumer, BooleanSupplier until) { + Objects.requireNonNull(consumer); + return new ForEachUntilOp<>(new VoidTerminalSink() { + @Override + public void accept(T t) { + consumer.accept(t); + } + + @Override + public boolean cancellationRequested() { + return until.getAsBoolean(); + } + }, StreamShape.REFERENCE); + } + + /** + * Construct a {@code ForEachUntilOp} that reads from an {@code IntStream} and sends the stream output to + * the provided {@code Consumer}, until the specified {@code BooleanProvider} indicates that no more input + * should be sent + * @param consumer The {@code Consumer} to send stream output to + * @param until A {@code BooleanSupplier} that indicates whether the termination criteria has occurred. Once + * it returns @{code true} the first time, it must continue to return {@code true} for all future + * invocations + */ + public static ForEachUntilOp make(final IntConsumer consumer, BooleanSupplier until) { + Objects.requireNonNull(consumer); + return new ForEachUntilOp<>(new VoidTerminalSink.OfInt() { + @Override + public void accept(int i) { + consumer.accept(i); + } + + @Override + public boolean cancellationRequested() { + return until.getAsBoolean(); + } + }, StreamShape.INT_VALUE); + } + + /** + * Construct a {@code ForEachUntilOp} that reads from a {@code LongStream} and sends the stream output to + * the provided {@code Consumer}, until the specified {@code BooleanProvider} indicates that no more input + * should be sent + * @param consumer The {@code Consumer} to send stream output to + * @param until A {@code BooleanSupplier} that indicates whether the termination criteria has occurred. Once + * it returns @{code true} the first time, it must continue to return {@code true} for all future + * invocations + */ + public static ForEachUntilOp make(final LongConsumer consumer, BooleanSupplier until) { + Objects.requireNonNull(consumer); + return new ForEachUntilOp<>(new VoidTerminalSink.OfLong() { + @Override + public void accept(long i) { + consumer.accept(i); + } + + @Override + public boolean cancellationRequested() { + return until.getAsBoolean(); + } + }, StreamShape.LONG_VALUE); + } + + /** + * Construct a {@code ForEachUntilOp} that reads from a {@code DoubleStream} and sends the stream output to + * the provided {@code Consumer}, until the specified {@code BooleanProvider} indicates that no more input + * should be sent + * @param consumer The {@code Consumer} to send stream output to + * @param until A {@code BooleanSupplier} that indicates whether the termination criteria has occurred. Once + * it returns @{code true} the first time, it must continue to return {@code true} for all future + * invocations + */ + public static ForEachUntilOp make(final DoubleConsumer consumer, BooleanSupplier until) { + Objects.requireNonNull(consumer); + return new ForEachUntilOp<>(new VoidTerminalSink.OfDouble() { + @Override + public void accept(double i) { + consumer.accept(i); + } + + @Override + public boolean cancellationRequested() { + return until.getAsBoolean(); + } + }, StreamShape.DOUBLE_VALUE); + } + + @Override + public int getOpFlags() { + return StreamOpFlag.IS_SHORT_CIRCUIT | StreamOpFlag.NOT_ORDERED; + } +}