changeset 7355:36482d2671d6

Javadoc for Stream
author briangoetz
date Tue, 19 Feb 2013 17:22:48 -0500
parents 493df51924c8
children c68ca847f63a
files src/share/classes/java/util/stream/DelegatingStream.java src/share/classes/java/util/stream/ReferencePipeline.java src/share/classes/java/util/stream/Stream.java
diffstat 3 files changed, 121 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/stream/DelegatingStream.java	Tue Feb 19 15:30:02 2013 -0500
+++ b/src/share/classes/java/util/stream/DelegatingStream.java	Tue Feb 19 17:22:48 2013 -0500
@@ -171,15 +171,15 @@
         return delegate.reduce(reducer);
     }
 
-    public <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator,
-                        BinaryOperator<U> reducer) {
-        return delegate.reduce(identity, accumulator, reducer);
+    public <U> U reduce(U identity, BiFunction<U, ? super T, U> reducer,
+                        BinaryOperator<U> combiner) {
+        return delegate.reduce(identity, reducer, combiner);
     }
 
     public <R> R collect(Supplier<R> resultFactory,
                          BiConsumer<R, ? super T> accumulator,
-                         BiConsumer<R, R> reducer) {
-        return delegate.collect(resultFactory, accumulator, reducer);
+                         BiConsumer<R, R> combiner) {
+        return delegate.collect(resultFactory, accumulator, combiner);
     }
 
     public <R> R collect(Collector<? super T, R> collector) {
--- a/src/share/classes/java/util/stream/ReferencePipeline.java	Tue Feb 19 15:30:02 2013 -0500
+++ b/src/share/classes/java/util/stream/ReferencePipeline.java	Tue Feb 19 17:22:48 2013 -0500
@@ -322,8 +322,8 @@
     }
 
     @Override
-    public <R> R reduce(R identity, BiFunction<R, ? super U, R> accumulator, BinaryOperator<R> reducer) {
-        return pipeline(FoldOp.makeRef(identity, accumulator, reducer));
+    public <R> R reduce(R identity, BiFunction<R, ? super U, R> reducer, BinaryOperator<R> combiner) {
+        return pipeline(FoldOp.makeRef(identity, reducer, combiner));
     }
 
     @Override
@@ -332,8 +332,8 @@
     }
 
     @Override
-    public <R> R collect(Supplier<R> resultFactory, BiConsumer<R, ? super U> accumulator, BiConsumer<R, R> reducer) {
-        return pipeline(FoldOp.makeRef(resultFactory, accumulator, reducer));
+    public <R> R collect(Supplier<R> resultFactory, BiConsumer<R, ? super U> accumulator, BiConsumer<R, R> combiner) {
+        return pipeline(FoldOp.makeRef(resultFactory, accumulator, combiner));
     }
 
     @Override
--- a/src/share/classes/java/util/stream/Stream.java	Tue Feb 19 15:30:02 2013 -0500
+++ b/src/share/classes/java/util/stream/Stream.java	Tue Feb 19 17:22:48 2013 -0500
@@ -41,6 +41,15 @@
 import java.util.function.ToIntFunction;
 import java.util.function.ToLongFunction;
 
+// @@@ Specification to-do list @@@
+// - Describe the difference between sequential and parallel streams
+// - More general information about reduce, better definitions for associativity, more description of
+//   how reduce employs parallelism, more examples
+// - Role of stream flags in various operations, specifically ordering
+// - Non-interference and constraints on lambda characteristics (e.g., side-effect-freedom)
+// - collectUnordered
+// @@@ Specification to-do list @@@
+
 /**
  * A sequence of elements supporting sequential and parallel bulk operations.  Streams support lazy transformative
  * operations (transforming a stream to another stream) such as {@code filter} and {@code map}, and consuming
@@ -371,16 +380,116 @@
      */
     Optional<T> reduce(BinaryOperator<T> reducer);
 
+    /**
+     * Perform a <em>reduction</em> on the elements of this stream, using the provided identity and combining
+     * functions.  This is equivalent to:
+     * <pre>
+     *     U result = identity;
+     *     for (T element : this stream)
+     *         result = reducer.apply(result, element)
+     *     return result;
+     * </pre>
+     *
+     * but is not constrained to execute sequentially.
+     *
+     * <p>The {@code identity} value must be an identity for the combiner function.  This means that for all {@code u},
+     * <code>combiner(identity, u)</code> is equal to {@code u}.  Additionally, the {@code combiner} function
+     * must be compatible with the {@code reducer} function; for all {@code u} and {@code t}, the following must hold:
+     * <pre>
+     *     combiner(u, reducer(identity, t)) == reducer(u, t)
+     * </pre>
+     *
+     * <p>This is a <a href="package-summary.html#StreamOps">terminal operation</a>.
+     *
+     * @apiNote Many reductions using this form can be represented more simply by an explicit combination of {@code map}
+     * and {@code reduce} operations.  The {@code reducer} function acts as a fused mapper and reducer, which can
+     * sometimes be more efficient than separate mapping and reduction, such as in the case where knowing the
+     * previously reduced value allows you to avoid some computation.
+     *
+     * @param identity The identity value for the combiner function
+     * @param reducer An function for combining two results
+     * @param combiner A function for incorporating an additional element into a result, which must be compatible
+     *                 with the reducer function
+     * @param <U> The type of the result
+     * @return The result of the reduction
+     * @see #reduce(BinaryOperator)
+     * @see #reduce(Object, BinaryOperator)
+     */
     <U> U reduce(U identity,
-                 BiFunction<U, ? super T, U> accumulator,
-                 BinaryOperator<U> reducer);
+                 BiFunction<U, ? super T, U> reducer,
+                 BinaryOperator<U> combiner);
 
+    /**
+     * Perform a <em>mutable reduction</em> operation on the elements of this stream.  A mutable reduction is one
+     * in which the reduced value is a mutable value holder, such as an {@code ArrayList}, and elements are incorporated
+     * by updating the state of the result rather than replacing the result.  This is equivalent to:
+     * <pre>
+     *     R result = resultFactory.get();
+     *     for (T element : this stream)
+     *         accumulator.accept(result, element);
+     *     return result;
+     * </pre>
+     *
+     * but is not constrained to execute sequentially.
+     *
+     * @apiNote There are many existing classes in the JDK whose signatures are a good match for use as
+     * arguments to {@code collect()}.  For example, the following will accumulate strings into an ArrayList:
+     * <pre>
+     *     List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
+     * </pre>
+     *
+     * The following will take a stream of strings and concatenates them into a single string:
+     * <pre>
+     *     String concat = stringStream.collect(StringBuilder::new, StringBuilder::append,
+     *                                          StringBuilder::append)
+     *                                 .toString();
+     * </pre>
+     *
+     * @param resultFactory Function that creates a new result container.  For a parallel execution, this function
+     *                      may be called multiple times and must return a fresh value each time.
+     * @param accumulator Function to incorporate a new value into a result container.
+     * @param combiner Function to incorporate the state of one result container into another
+     * @param <R> Type of the result
+     * @return The result of the reduction
+     */
     <R> R collect(Supplier<R> resultFactory,
                   BiConsumer<R, ? super T> accumulator,
-                  BiConsumer<R, R> reducer);
+                  BiConsumer<R, R> combiner);
 
+    /** Perform a <em>mutable reduction</em> operation on the elements of this stream using a {@code Collector}
+     * object to describe the reduction.  A {@code Collector} encapsulates the functions used as arguments
+     * to {@link #collect(Supplier, BiConsumer, BiConsumer)}, allowing for reuse of collection strategies
+     * and composition of collect operations such as multiple-level group-by.
+     *
+     * @apiNote
+     * The following will accumulate strings into an ArrayList:
+     * <pre>
+     *     List<String> asList = stringStream.collect(Collectors.toList());
+     * </pre>
+     *
+     * The following will classify {@code Person} objects by city:
+     * <pre>
+     *     Map<String, Collection<Person>> peopleByCity
+     *         = personStream.collect(Collectors.groupBy(Person::getCity));
+     * </pre>
+     *
+     * The following will classify {@code Person} objects by state and city, cascading two {@code Collector}s
+     * together:
+     * <pre>
+     *     Map<String, Map<String, Collection<Person>>> peopleByStateAndCity
+     *         = personStream.collect(Collectors.groupBy(Person::getState,
+     *                                                   Collectors.groupBy(Person::getCity)));
+     * </pre>
+     *
+     * @param collector The {@code Collector} describing the reduction
+     * @param <R> The type of the result
+     * @return The result of the reduction
+     * @see #collect(Supplier, BiConsumer, BiConsumer)
+     * @see Collectors
+     */
     <R> R collect(Collector<? super T, R> collector);
 
+    // @@@ Spec needed
     <R> R collectUnordered(Collector<? super T, R> collector);
 
     /**