changeset 16503:871cb8793270

8130023: API java.util.stream: explicitly specify guaranteed execution of the pipeline Reviewed-by: briangoetz, redestad
author psandoz
date Fri, 20 May 2016 11:47:39 +0200
parents 078eda57a82b
children b15047a04378
files src/java.base/share/classes/java/util/stream/DoubleStream.java src/java.base/share/classes/java/util/stream/IntStream.java src/java.base/share/classes/java/util/stream/LongStream.java src/java.base/share/classes/java/util/stream/Stream.java src/java.base/share/classes/java/util/stream/package-info.java
diffstat 5 files changed, 58 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/util/stream/DoubleStream.java	Thu May 19 21:59:35 2016 -0700
+++ b/src/java.base/share/classes/java/util/stream/DoubleStream.java	Fri May 20 11:47:39 2016 +0200
@@ -211,6 +211,11 @@
      *         .sum();
      * }</pre>
      *
+     * <p>In cases where stream implementation is able to optimize away the
+     * production of some or all the elements (such as with short-circuiting
+     * operations like {@code findFirst}, or in the example described in
+     * {@link #count}), the action will not be invoked for those elements.
+     *
      * @param action a <a href="package-summary.html#NonInterference">
      *               non-interfering</a> action to perform on the elements as
      *               they are consumed from the stream
--- a/src/java.base/share/classes/java/util/stream/IntStream.java	Thu May 19 21:59:35 2016 -0700
+++ b/src/java.base/share/classes/java/util/stream/IntStream.java	Fri May 20 11:47:39 2016 +0200
@@ -209,6 +209,11 @@
      *         .sum();
      * }</pre>
      *
+     * <p>In cases where stream implementation is able to optimize away the
+     * production of some or all the elements (such as with short-circuiting
+     * operations like {@code findFirst}, or in the example described in
+     * {@link #count}), the action will not be invoked for those elements.
+     *
      * @param action a <a href="package-summary.html#NonInterference">
      *               non-interfering</a> action to perform on the elements as
      *               they are consumed from the stream
--- a/src/java.base/share/classes/java/util/stream/LongStream.java	Thu May 19 21:59:35 2016 -0700
+++ b/src/java.base/share/classes/java/util/stream/LongStream.java	Fri May 20 11:47:39 2016 +0200
@@ -209,6 +209,11 @@
      *         .sum();
      * }</pre>
      *
+     * <p>In cases where stream implementation is able to optimize away the
+     * production of some or all the elements (such as with short-circuiting
+     * operations like {@code findFirst}, or in the example described in
+     * {@link #count}), the action will not be invoked for those elements.
+     *
      * @param action a <a href="package-summary.html#NonInterference">
      *               non-interfering</a> action to perform on the elements as
      *               they are consumed from the stream
--- a/src/java.base/share/classes/java/util/stream/Stream.java	Thu May 19 21:59:35 2016 -0700
+++ b/src/java.base/share/classes/java/util/stream/Stream.java	Fri May 20 11:47:39 2016 +0200
@@ -82,6 +82,19 @@
  * terminal operation is initiated, and source elements are consumed only
  * as needed.
  *
+ * <p>A stream implementation is permitted significant latitude in optimizing
+ * the computation of the result.  For example, a stream implementation is free
+ * to elide operations (or entire stages) from a stream pipeline -- and
+ * therefore elide invocation of behavioral parameters -- if it can prove that
+ * it would not affect the result of the computation.  This means that
+ * side-effects of behavioral parameters may not always be executed and should
+ * not be relied upon, unless otherwise specified (such as by the terminal
+ * operations {@code forEach} and {@code forEachOrdered}). (For a specific
+ * example of such an optimization, see the API note documented on the
+ * {@link #count} operation.  For more detail, see the
+ * <a href="package-summary.html#SideEffects">side-effects</a> section of the
+ * strean package documentation.)
+ *
  * <p>Collections and streams, while bearing some superficial similarities,
  * have different goals.  Collections are primarily concerned with the efficient
  * management of, and access to, their elements.  By contrast, streams do not
@@ -415,6 +428,11 @@
      *         .collect(Collectors.toList());
      * }</pre>
      *
+     * <p>In cases where stream implementation is able to optimize away the
+     * production of some or all the elements (such as with short-circuiting
+     * operations like {@code findFirst}, or in the example described in
+     * {@link #count}), the action will not be invoked for those elements.
+     *
      * @param action a <a href="package-summary.html#NonInterference">
      *                 non-interfering</a> action to perform on the elements as
      *                 they are consumed from the stream
--- a/src/java.base/share/classes/java/util/stream/package-info.java	Thu May 19 21:59:35 2016 -0700
+++ b/src/java.base/share/classes/java/util/stream/package-info.java	Fri May 20 11:47:39 2016 +0200
@@ -287,18 +287,35 @@
  * statelessness requirement, as well as other thread-safety hazards.
  *
  * <p>If the behavioral parameters do have side-effects, unless explicitly
- * stated, there are no guarantees as to the
- * <a href="../concurrent/package-summary.html#MemoryVisibility"><i>visibility</i></a>
- * of those side-effects to other threads, nor are there any guarantees that
- * different operations on the "same" element within the same stream pipeline
- * are executed in the same thread.  Further, the ordering of those effects
- * may be surprising.  Even when a pipeline is constrained to produce a
- * <em>result</em> that is consistent with the encounter order of the stream
- * source (for example, {@code IntStream.range(0,5).parallel().map(x -> x*2).toArray()}
+ * stated, there are no guarantees as to:
+ * <ul>
+ *    <li>the <a href="../concurrent/package-summary.html#MemoryVisibility">
+ *    <i>visibility</i></a> of those side-effects to other threads;</li>
+ *    <li>that different operations on the "same" element within the same stream
+ *    pipeline are executed in the same thread; and</li>
+ *    <li>that behavioral parameters are always invoked, since a stream
+ *    implementation is free to elide operations (or entire stages) from a
+ *    stream pipeline if it can prove that it would not affect the result of the
+ *    computation.
+ *    </li>
+ * </ul>
+ * <p>The ordering of side-effects may be surprising.  Even when a pipeline is
+ * constrained to produce a <em>result</em> that is consistent with the
+ * encounter order of the stream source (for example,
+ * {@code IntStream.range(0,5).parallel().map(x -> x*2).toArray()}
  * must produce {@code [0, 2, 4, 6, 8]}), no guarantees are made as to the order
  * in which the mapper function is applied to individual elements, or in what
  * thread any behavioral parameter is executed for a given element.
  *
+ * <p>The eliding of side-effects may also be surprising.  With the exception of
+ * terminal operations {@link java.util.stream.Stream#forEach forEach} and
+ * {@link java.util.stream.Stream#forEachOrdered forEachOrdered}, side-effects
+ * of behavioral parameters may not always be executed when the stream
+ * implementation can optimize away the execution of behavioral parameters
+ * without affecting the result of the computation.  (For a specific example
+ * see the API note documented on the {@link java.util.stream.Stream#count count}
+ * operation.)
+ *
  * <p>Many computations where one might be tempted to use side effects can be more
  * safely and efficiently expressed without side-effects, such as using
  * <a href="package-summary.html#Reduction">reduction</a> instead of mutable