< prev index next >

src/java.base/share/classes/java/util/stream/package-info.java

Print this page




 299  *    computation.
 300  *    </li>
 301  * </ul>
 302  * <p>The ordering of side-effects may be surprising.  Even when a pipeline is
 303  * constrained to produce a <em>result</em> that is consistent with the
 304  * encounter order of the stream source (for example,
 305  * {@code IntStream.range(0,5).parallel().map(x -> x*2).toArray()}
 306  * must produce {@code [0, 2, 4, 6, 8]}), no guarantees are made as to the order
 307  * in which the mapper function is applied to individual elements, or in what
 308  * thread any behavioral parameter is executed for a given element.
 309  *
 310  * <p>The eliding of side-effects may also be surprising.  With the exception of
 311  * terminal operations {@link java.util.stream.Stream#forEach forEach} and
 312  * {@link java.util.stream.Stream#forEachOrdered forEachOrdered}, side-effects
 313  * of behavioral parameters may not always be executed when the stream
 314  * implementation can optimize away the execution of behavioral parameters
 315  * without affecting the result of the computation.  (For a specific example
 316  * see the API note documented on the {@link java.util.stream.Stream#count count}
 317  * operation.)
 318  *
 319  * <p>Many computations where one might be tempted to use side effects can be more
 320  * safely and efficiently expressed without side-effects, such as using
 321  * <a href="package-summary.html#Reduction">reduction</a> instead of mutable
 322  * accumulators. However, side-effects such as using {@code println()} for debugging
 323  * purposes are usually harmless.  A small number of stream operations, such as
 324  * {@code forEach()} and {@code peek()}, can operate only via side-effects;
 325  * these should be used with care.
 326  *
 327  * <p>As an example of how to transform a stream pipeline that inappropriately
 328  * uses side-effects to one that does not, the following code searches a stream
 329  * of strings for those matching a given regular expression, and puts the
 330  * matches in a list.
 331  *
 332  * <pre>{@code
 333  *     ArrayList<String> results = new ArrayList<>();
 334  *     stream.filter(s -> pattern.matcher(s).matches())
 335  *           .forEach(s -> results.add(s));  // Unnecessary use of side-effects!
 336  * }</pre>
 337  *
 338  * This code unnecessarily uses side-effects.  If executed in parallel, the
 339  * non-thread-safety of {@code ArrayList} would cause incorrect results, and


 428  *
 429  * <p>These reduction operations can run safely in parallel with almost no
 430  * modification:
 431  * <pre>{@code
 432  *    int sum = numbers.parallelStream().reduce(0, Integer::sum);
 433  * }</pre>
 434  *
 435  * <p>Reduction parallellizes well because the implementation
 436  * can operate on subsets of the data in parallel, and then combine the
 437  * intermediate results to get the final correct answer.  (Even if the language
 438  * had a "parallel for-each" construct, the mutative accumulation approach would
 439  * still required the developer to provide
 440  * thread-safe updates to the shared accumulating variable {@code sum}, and
 441  * the required synchronization would then likely eliminate any performance gain from
 442  * parallelism.)  Using {@code reduce()} instead removes all of the
 443  * burden of parallelizing the reduction operation, and the library can provide
 444  * an efficient parallel implementation with no additional synchronization
 445  * required.
 446  *
 447  * <p>The "widgets" examples shown earlier shows how reduction combines with
 448  * other operations to replace for loops with bulk operations.  If {@code widgets}
 449  * is a collection of {@code Widget} objects, which have a {@code getWeight} method,
 450  * we can find the heaviest widget with:
 451  * <pre>{@code
 452  *     OptionalInt heaviest = widgets.parallelStream()
 453  *                                   .mapToInt(Widget::getWeight)
 454  *                                   .max();
 455  * }</pre>
 456  *
 457  * <p>In its more general form, a {@code reduce} operation on elements of type
 458  * {@code <T>} yielding a result of type {@code <U>} requires three parameters:
 459  * <pre>{@code
 460  * <U> U reduce(U identity,
 461  *              BiFunction<U, ? super T, U> accumulator,
 462  *              BinaryOperator<U> combiner);
 463  * }</pre>
 464  * Here, the <em>identity</em> element is both an initial seed value for the reduction
 465  * and a default result if there are no input elements. The <em>accumulator</em>
 466  * function takes a partial result and the next element, and produces a new
 467  * partial result. The <em>combiner</em> function combines two partial results
 468  * to produce a new partial result.  (The combiner is necessary in parallel




 299  *    computation.
 300  *    </li>
 301  * </ul>
 302  * <p>The ordering of side-effects may be surprising.  Even when a pipeline is
 303  * constrained to produce a <em>result</em> that is consistent with the
 304  * encounter order of the stream source (for example,
 305  * {@code IntStream.range(0,5).parallel().map(x -> x*2).toArray()}
 306  * must produce {@code [0, 2, 4, 6, 8]}), no guarantees are made as to the order
 307  * in which the mapper function is applied to individual elements, or in what
 308  * thread any behavioral parameter is executed for a given element.
 309  *
 310  * <p>The eliding of side-effects may also be surprising.  With the exception of
 311  * terminal operations {@link java.util.stream.Stream#forEach forEach} and
 312  * {@link java.util.stream.Stream#forEachOrdered forEachOrdered}, side-effects
 313  * of behavioral parameters may not always be executed when the stream
 314  * implementation can optimize away the execution of behavioral parameters
 315  * without affecting the result of the computation.  (For a specific example
 316  * see the API note documented on the {@link java.util.stream.Stream#count count}
 317  * operation.)
 318  *
 319  * <p>Many computations where one might be tempted to use side-effects can be more
 320  * safely and efficiently expressed without side-effects, such as using
 321  * <a href="package-summary.html#Reduction">reduction</a> instead of mutable
 322  * accumulators. However, side-effects such as using {@code println()} for debugging
 323  * purposes are usually harmless.  A small number of stream operations, such as
 324  * {@code forEach()} and {@code peek()}, can operate only via side-effects;
 325  * these should be used with care.
 326  *
 327  * <p>As an example of how to transform a stream pipeline that inappropriately
 328  * uses side-effects to one that does not, the following code searches a stream
 329  * of strings for those matching a given regular expression, and puts the
 330  * matches in a list.
 331  *
 332  * <pre>{@code
 333  *     ArrayList<String> results = new ArrayList<>();
 334  *     stream.filter(s -> pattern.matcher(s).matches())
 335  *           .forEach(s -> results.add(s));  // Unnecessary use of side-effects!
 336  * }</pre>
 337  *
 338  * This code unnecessarily uses side-effects.  If executed in parallel, the
 339  * non-thread-safety of {@code ArrayList} would cause incorrect results, and


 428  *
 429  * <p>These reduction operations can run safely in parallel with almost no
 430  * modification:
 431  * <pre>{@code
 432  *    int sum = numbers.parallelStream().reduce(0, Integer::sum);
 433  * }</pre>
 434  *
 435  * <p>Reduction parallellizes well because the implementation
 436  * can operate on subsets of the data in parallel, and then combine the
 437  * intermediate results to get the final correct answer.  (Even if the language
 438  * had a "parallel for-each" construct, the mutative accumulation approach would
 439  * still required the developer to provide
 440  * thread-safe updates to the shared accumulating variable {@code sum}, and
 441  * the required synchronization would then likely eliminate any performance gain from
 442  * parallelism.)  Using {@code reduce()} instead removes all of the
 443  * burden of parallelizing the reduction operation, and the library can provide
 444  * an efficient parallel implementation with no additional synchronization
 445  * required.
 446  *
 447  * <p>The "widgets" examples shown earlier shows how reduction combines with
 448  * other operations to replace for-loops with bulk operations.  If {@code widgets}
 449  * is a collection of {@code Widget} objects, which have a {@code getWeight} method,
 450  * we can find the heaviest widget with:
 451  * <pre>{@code
 452  *     OptionalInt heaviest = widgets.parallelStream()
 453  *                                   .mapToInt(Widget::getWeight)
 454  *                                   .max();
 455  * }</pre>
 456  *
 457  * <p>In its more general form, a {@code reduce} operation on elements of type
 458  * {@code <T>} yielding a result of type {@code <U>} requires three parameters:
 459  * <pre>{@code
 460  * <U> U reduce(U identity,
 461  *              BiFunction<U, ? super T, U> accumulator,
 462  *              BinaryOperator<U> combiner);
 463  * }</pre>
 464  * Here, the <em>identity</em> element is both an initial seed value for the reduction
 465  * and a default result if there are no input elements. The <em>accumulator</em>
 466  * function takes a partial result and the next element, and produces a new
 467  * partial result. The <em>combiner</em> function combines two partial results
 468  * to produce a new partial result.  (The combiner is necessary in parallel


< prev index next >