< prev index next >

src/java.base/share/classes/java/util/stream/Stream.java

Print this page
rev 12299 : 8071597: Add Stream limit and skip operations that take a predicate
Reviewed-by: briangoetz, smarks, chegar, forax

*** 22,32 **** * or visit www.oracle.com if you need additional information or have any * questions. */ package java.util.stream; - import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; --- 22,31 ----
*** 479,488 **** --- 478,616 ---- * @throws IllegalArgumentException if {@code n} is negative */ Stream<T> skip(long n); /** + * Returns, if this stream is ordered, a stream consisting of the longest + * prefix of elements taken from this stream that match the given predicate. + * Otherwise returns, if this stream is unordered, a stream consisting of a + * subset of elements taken from this stream that match the given predicate. + * + * <p>If this stream is ordered then the longest prefix is a contiguous + * sequence of elements of this stream that match the given predicate. The + * first element of the sequence is the first element of this stream, and + * the element immediately following the last element of the sequence does + * not match the given predicate. + * + * <p>If this stream is unordered, and some (but not all) elements of this + * stream match the given predicate, then the behavior of this operation is + * nondeterministic; it is free to take any subset of matching elements + * (which includes the empty set). + * + * <p>Independent of whether this stream is ordered or unordered if all + * elements of this stream match the given predicate then this operation + * takes all elements (the result is the same is the input), or if no + * elements of the stream match the given predicate then no elements are + * taken (the result is an empty stream). + * + * <p>This is a <a href="package-summary.html#StreamOps">short-circuiting + * stateful intermediate operation</a>. + * + * @implSpec + * The default implementation obtains the {@link #spliterator() spliterator} + * of this stream, wraps that spliterator so as to support the semantics + * of this operation on traversal, and returns a new stream associated with + * the wrapped spliterator. The returned stream preserves the execution + * characteristics of this stream (namely parallel or sequential execution + * as per {@link #isParallel()}) but the wrapped spliterator may choose to + * not support splitting. When the returned stream is closed, the close + * handlers for both the returned and this stream are invoked. + * + * @apiNote + * While {@code takeWhile()} is generally a cheap operation on sequential + * stream pipelines, it can be quite expensive on ordered parallel + * pipelines, since the operation is constrained to return not just any + * valid prefix, but the longest prefix of elements in the encounter order. + * Using an unordered stream source (such as {@link #generate(Supplier)}) or + * removing the ordering constraint with {@link #unordered()} may result in + * significant speedups of {@code takeWhile()} in parallel pipelines, if the + * semantics of your situation permit. If consistency with encounter order + * is required, and you are experiencing poor performance or memory + * utilization with {@code takeWhile()} in parallel pipelines, switching to + * sequential execution with {@link #sequential()} may improve performance. + * + * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>, + * <a href="package-summary.html#Statelessness">stateless</a> + * predicate to apply to elements to determine the longest + * prefix of elements. + * @return the new stream + */ + default Stream<T> takeWhile(Predicate<? super T> predicate) { + Objects.requireNonNull(predicate); + // Reuses the unordered spliterator, which, when encounter is present, + // is safe to use as long as it configured not to split + return StreamSupport.stream( + new WhileOps.UnorderedWhileSpliterator.OfRef.Taking<>(spliterator(), true, predicate), + isParallel()).onClose(this::close); + } + + /** + * Returns, if this stream is ordered, a stream consisting of the remaining + * elements of this stream after dropping the longest prefix of elements + * that match the given predicate. Otherwise returns, if this stream is + * unordered, a stream consisting of the remaining elements of this stream + * after dropping a subset of elements that match the given predicate. + * + * <p>If this stream is ordered then the longest prefix is a contiguous + * sequence of elements of this stream that match the given predicate. The + * first element of the sequence is the first element of this stream, and + * the element immediately following the last element of the sequence does + * not match the given predicate. + * + * <p>If this stream is unordered, and some (but not all) elements of this + * stream match the given predicate, then the behavior of this operation is + * nondeterministic; it is free to drop any subset of matching elements + * (which includes the empty set). + * + * <p>Independent of whether this stream is ordered or unordered if all + * elements of this stream match the given predicate then this operation + * drops all elements (the result is an empty stream), or if no elements of + * the stream match the given predicate then no elements are dropped (the + * result is the same is the input). + * + * <p>This is a <a href="package-summary.html#StreamOps">stateful + * intermediate operation</a>. + * + * @implSpec + * The default implementation obtains the {@link #spliterator() spliterator} + * of this stream, wraps that spliterator so as to support the semantics + * of this operation on traversal, and returns a new stream associated with + * the wrapped spliterator. The returned stream preserves the execution + * characteristics of this stream (namely parallel or sequential execution + * as per {@link #isParallel()}) but the wrapped spliterator may choose to + * not support splitting. When the returned stream is closed, the close + * handlers for both the returned and this stream are invoked. + * + * @apiNote + * While {@code dropWhile()} is generally a cheap operation on sequential + * stream pipelines, it can be quite expensive on ordered parallel + * pipelines, since the operation is constrained to return not just any + * valid prefix, but the longest prefix of elements in the encounter order. + * Using an unordered stream source (such as {@link #generate(Supplier)}) or + * removing the ordering constraint with {@link #unordered()} may result in + * significant speedups of {@code dropWhile()} in parallel pipelines, if the + * semantics of your situation permit. If consistency with encounter order + * is required, and you are experiencing poor performance or memory + * utilization with {@code dropWhile()} in parallel pipelines, switching to + * sequential execution with {@link #sequential()} may improve performance. + * + * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>, + * <a href="package-summary.html#Statelessness">stateless</a> + * predicate to apply to elements to determine the longest + * prefix of elements. + * @return the new stream + */ + default Stream<T> dropWhile(Predicate<? super T> predicate) { + Objects.requireNonNull(predicate); + // Reuses the unordered spliterator, which, when encounter is present, + // is safe to use as long as it configured not to split + return StreamSupport.stream( + new WhileOps.UnorderedWhileSpliterator.OfRef.Dropping<>(spliterator(), true, predicate), + isParallel()).onClose(this::close); + } + + /** * Performs an action for each element of this stream. * * <p>This is a <a href="package-summary.html#StreamOps">terminal * operation</a>. *
< prev index next >