changeset 7328:41511221ac77

JavaDoc.
author psandoz
date Thu, 14 Feb 2013 15:05:20 +0100
parents e8f0df769883
children d2982a5d8327
files src/share/classes/java/util/stream/NodeUtils.java src/share/classes/java/util/stream/Nodes.java src/share/classes/java/util/stream/PipelineHelper.java
diffstat 3 files changed, 388 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/stream/NodeUtils.java	Wed Feb 13 18:37:46 2013 -0800
+++ b/src/share/classes/java/util/stream/NodeUtils.java	Thu Feb 14 15:05:20 2013 +0100
@@ -31,9 +31,9 @@
 import java.util.function.IntFunction;
 
 /**
- * Utilities for generating and operating on reference-based Nodes.
+ * Fork/Join-based parallel computing utilities for collecting output from a {@link PipelineHelper}
+ * to a {@link Node} and flattening a {@link Node}.
  *
- * @author Brian Goetz
  */
 final class NodeUtils {
 
@@ -41,6 +41,28 @@
         throw new Error("no instances");
     }
 
+    /**
+     * Collect, in parallel, elements output from a pipeline and encapsulate those elements
+     * in a (reference) {@link Node}.
+     *
+     * @implSpec
+     * If the exact size of the output from the pipeline is known and the source {@link Spliterator}
+     * has the {@link Spliterator#SUBSIZED} characteristic then a flat {@link Node} will be returned
+     * whose content is an array. Since the size is known the array can be constructed in advance and
+     * output elements can be placed into the array concurrently, by leaf Fork/Join tasks,
+     * at the correct offsets.
+     * If the exact size is not known then output elements are collected into a conc-{@code Node} whose
+     * shape mirrors that of the computation. This conc-{@code Node} can then be flattened in parallel
+     * to produce a flat {@code Node} whose content is an array.
+     *
+     * @param helper the pipeline helper capturing the pipeline.
+     * @param flattenTree if true the returned {@link Node} is flat and has no children, otherwise
+     *                    the {@link Node} may be a root node in a tree whose shape mirrors that of the
+     *                    parallel computation.
+     * @param <P_IN> type of input elements to the pipeline
+     * @param <P_OUT> type of output elements from the pipeline
+     * @return the {@link Node} encapsulating the output elements.
+     */
     public static <P_IN, P_OUT> Node<P_OUT> collect(PipelineHelper<P_IN, P_OUT> helper,
                                                     boolean flattenTree) {
         Spliterator<P_IN> spliterator = helper.sourceSpliterator();
@@ -59,6 +81,20 @@
         }
     }
 
+    /**
+     * Flatten, in parallel, a {@link Node}.
+     *
+     * @implSpec
+     * An array will be created, from the generator, whose length is {@link Node#count()}.
+     * Then the node tree will be traversed and leaf node elements will be placed into the array
+     * concurrently, by leaf Fork/Join tasks, at the correct offsets.
+     *
+     * @param node the node to flatten.
+     * @param generator the array factory to be utilized to create array instances.
+     * @param <T> type of elements contained by the node
+     * @return a flattened {@code Node}. If the input node is already flat then
+     * that node is returned directly.
+     */
     public static <T> Node<T> flatten(Node<T> node, IntFunction<T[]> generator) {
         if (node.getChildCount() > 0) {
             T[] array = generator.apply((int) node.count());
@@ -71,8 +107,29 @@
 
     // Ints
 
+    /**
+     * Collect, in parallel, {@code int} elements output from a pipeline and encapsulate those elements
+     * in a {@link Node.OfInt}.
+     *
+     * @implSpec
+     * If the exact size of the output from the pipeline is known and the source {@link Spliterator}
+     * has the {@link Spliterator#SUBSIZED} characteristic then a flat {@link Node.OfInt} will be returned
+     * whose content is an int[] array. Since the size is known the array can be constructed in advance and
+     * output elements can be placed into the array concurrently, by leaf Fork/Join tasks,
+     * at the correct offsets.
+     * If the exact size is not known then output elements are collected into a conc-{@code Node.OfInt} whose
+     * shape mirrors that of the computation. This conc-{@code Node.OfInt} can then be flattened in parallel
+     * to produce a flat {@code Node.OfInt} whose content is an int[] array.
+     *
+     * @param helper the pipeline helper capturing the pipeline.
+     * @param flattenTree if true the returned {@link Node.OfInt} is flat and has no children, otherwise
+     *                    the {@link Node.OfInt} may be a root node in a tree whose shape mirrors that of the
+     *                    parallel computation.
+     * @param <P_IN> type of input elements to the pipeline
+     * @return the {@link Node.OfInt} encapsulating the output elements.
+     */
     public static <P_IN> Node.OfInt intCollect(PipelineHelper<P_IN, Integer> helper,
-                                                           boolean flattenTree) {
+                                               boolean flattenTree) {
         Spliterator<P_IN> spliterator = helper.sourceSpliterator();
         long size = helper.exactOutputSizeIfKnown(spliterator);
         if (size >= 0 && spliterator.hasCharacteristic(Spliterator.SUBSIZED)) {
@@ -90,6 +147,18 @@
         }
     }
 
+    /**
+     * Flatten, in parallel, a {@link Node.OfInt}.
+     *
+     * @implSpec
+     * An int[] array will be created whose length is {@link Node.OfInt#count()}.
+     * Then the node tree will be traversed and leaf node elements will be placed into the array
+     * concurrently, by leaf Fork/Join tasks, at the correct offsets.
+     *
+     * @param node the node to flatten.
+     * @return a flattened {@code Node.OfInt}. If the input node is already flat then
+     * that node is returned directly.
+     */
     public static Node.OfInt intFlatten(Node.OfInt node) {
         if (node.getChildCount() > 0) {
             int[] array = new int[(int) node.count()];
@@ -102,6 +171,27 @@
 
     // Longs
 
+    /**
+     * Collect, in parallel, {@code long} elements output from a pipeline and encapsulate those elements
+     * in a {@link Node.OfLong}.
+     *
+     * @implSpec
+     * If the exact size of the output from the pipeline is known and the source {@link Spliterator}
+     * has the {@link Spliterator#SUBSIZED} characteristic then a flat {@link Node.OfLong} will be returned
+     * whose content is an long[] array. Since the size is known the array can be constructed in advance and
+     * output elements can be placed into the array concurrently, by leaf Fork/Join tasks,
+     * at the correct offsets.
+     * If the exact size is not known then output elements are collected into a conc-{@code Node.OfLong} whose
+     * shape mirrors that of the computation. This conc-{@code Node.OfLong} can then be flattened in parallel
+     * to produce a flat {@code Node.OfLong} whose content is an long[] array.
+     *
+     * @param helper the pipeline helper capturing the pipeline.
+     * @param flattenTree if true the returned {@link Node.OfLong} is flat and has no children, otherwise
+     *                    the {@link Node.OfLong} may be a root node in a tree whose shape mirrors that of the
+     *                    parallel computation.
+     * @param <P_IN> type of input elements to the pipeline
+     * @return the {@link Node.OfLong} encapsulating the output elements.
+     */
     public static <P_IN> Node.OfLong longCollect(PipelineHelper<P_IN, Long> helper,
                                                               boolean flattenTree) {
         Spliterator<P_IN> spliterator = helper.sourceSpliterator();
@@ -121,6 +211,18 @@
         }
     }
 
+    /**
+     * Flatten, in parallel, a {@link Node.OfLong}.
+     *
+     * @implSpec
+     * An long[] array will be created whose length is {@link Node.OfLong#count()}.
+     * Then the node tree will be traversed and leaf node elements will be placed into the array
+     * concurrently, by leaf Fork/Join tasks, at the correct offsets.
+     *
+     * @param node the node to flatten.
+     * @return a flattened {@code Node.OfLong}. If the input node is already flat then
+     * that node is returned directly.
+     */
     public static Node.OfLong longFlatten(Node.OfLong node) {
         if (node.getChildCount() > 0) {
             long[] array = new long[(int) node.count()];
@@ -133,6 +235,27 @@
 
     // Doubles
 
+    /**
+     * Collect, in parallel, {@code double} elements output from a pipeline and encapsulate those elements
+     * in a {@link Node.OfDouble}.
+     *
+     * @implSpec
+     * If the exact size of the output from the pipeline is known and the source {@link Spliterator}
+     * has the {@link Spliterator#SUBSIZED} characteristic then a flat {@link Node.OfDouble} will be returned
+     * whose content is an double[] array. Since the size is known the array can be constructed in advance and
+     * output elements can be placed into the array concurrently, by leaf Fork/Join tasks,
+     * at the correct offsets.
+     * If the exact size is not known then output elements are collected into a conc-{@code Node.OfDouble} whose
+     * shape mirrors that of the computation. This conc-{@code Node.OfDouble} can then be flattened in parallel
+     * to produce a flat {@code Node.OfDouble} whose content is an double[] array.
+     *
+     * @param helper the pipeline helper capturing the pipeline.
+     * @param flattenTree if true the returned {@link Node.OfDouble} is flat and has no children, otherwise
+     *                    the {@link Node.OfDouble} may be a root node in a tree whose shape mirrors that of the
+     *                    parallel computation.
+     * @param <P_IN> type of input elements to the pipeline
+     * @return the {@link Node.OfDouble} encapsulating the output elements.
+     */
     public static <P_IN> Node.OfDouble doubleCollect(PipelineHelper<P_IN, Double> helper,
                                                             boolean flattenTree) {
         Spliterator<P_IN> spliterator = helper.sourceSpliterator();
@@ -152,6 +275,18 @@
         }
     }
 
+    /**
+     * Flatten, in parallel, a {@link Node.OfDouble}.
+     *
+     * @implSpec
+     * An double[] array will be created whose length is {@link Node.OfDouble#count()}.
+     * Then the node tree will be traversed and leaf node elements will be placed into the array
+     * concurrently, by leaf Fork/Join tasks, at the correct offsets.
+     *
+     * @param node the node to flatten.
+     * @return a flattened {@code Node.OfDouble}. If the input node is already flat then
+     * that node is returned directly.
+     */
     public static Node.OfDouble doubleFlatten(Node.OfDouble node) {
         if (node.getChildCount() > 0) {
             double[] array = new double[(int) node.count()];
@@ -162,7 +297,6 @@
         }
     }
 
-
     // Reference implementations
 
     private static class CollectorTask<T, U> extends AbstractTask<T, U, Node<U>, CollectorTask<T, U>> {
--- a/src/share/classes/java/util/stream/Nodes.java	Wed Feb 13 18:37:46 2013 -0800
+++ b/src/share/classes/java/util/stream/Nodes.java	Thu Feb 14 15:05:20 2013 +0100
@@ -37,6 +37,11 @@
 
 import static java.util.stream.Collectors.toStringJoiner;
 
+/**
+ * Factory methods for constructing implementations of {@link Node} and {@link Node.Builder}
+ * and primitive specializations of.
+ *
+ */
 final class Nodes {
 
     private Nodes() {
@@ -68,7 +73,7 @@
     }
 
     /**
-     * Create a concatenated node that has two or more children.
+     * Create a concatenated {@link Node} that has two or more children.
      * <p>The count of the concatenated node is equal to the sum
      * of the count of each child. Traversal of the concatenated node
      * traverses the content of each child in encounter order of the list of children.
@@ -77,7 +82,7 @@
      *
      * @param shape the shape of the concatenated node to be created
      * @param nodes the list of child nodes.
-     * @param <T> the type of elements of the created node.
+     * @param <T> the type of elements of the concatenated node.
      * @return a concatenated node if the size of the list is > 1. If the size is 0 then an
      * empty node is returned (see {@link #emptyNode()}). If the size is 1 then the single
      * node contained in the list is returned.
@@ -127,13 +132,13 @@
     }
 
     /**
-     * Created a truncated node from an input node.
+     * Created a truncated {@link Node} from an input {@link Node}.
      *
      * @param input the input node.
      * @param from the offset from which to truncate from
      * @param to the offset form which to truncate up to (but not including)
-     * @param generator the array generated
-     * @param <T> the type of elements of the created node.
+     * @param generator the array factory
+     * @param <T> the type of elements of the input node and truncated node.
      * @return the truncated node.
      */
     public static <T> Node<T> createTruncatedNode(Node<T> input, long from, long to, IntFunction<T[]> generator) {
@@ -151,20 +156,84 @@
         }
     }
 
-    //
+    // Reference-based node methods
 
+    /**
+     * Create an empty (reference) {@link Node}.
+     *
+     * @param <T> the type of elements held by the node.
+     * @return an empty node.
+     */
     public static<T> Node<T> emptyNode() {
         return (Node<T>) EMPTY_NODE;
     }
 
-    public static<T> Node<T> node(final T[] array) {
+    /**
+     * Create a (reference) {@link Node} whose contents is an array.
+     * <p>
+     * The created node will hold the reference to the array and will not make
+     * a copy.
+     *
+     * @param array the array.
+     * @param <T> the type of elements held by the node.
+     * @return a node holding an array.
+     */
+    public static<T> Node<T> node(T[] array) {
         return new ArrayNode<>(array);
     }
 
+    /**
+     * Create a (reference) {@link Node} whose contents is a {@link Collection}.
+     * <p>
+     * The created node will hold the reference to the collection and will not make
+     * a copy.
+     *
+     * @param c the collection.
+     * @param <T> the type of elements held by the node.
+     * @return a node holding a collection.
+     */
     public static<T> Node<T> node(Collection<T> c) {
         return new CollectionNode<>(c);
     }
 
+    /**
+     * Create a concatenated (reference) {@link Node} that has two or more children.
+     * <p>The count of the concatenated node is equal to the sum
+     * of the count of each child. Traversal of the concatenated node
+     * traverses the content of each child in encounter order of the list of children.
+     * Splitting a spliterator obtained from the concatenated node preserves
+     * the encounter order of the list of children.
+     *
+     * @param nodes the list of child nodes.
+     * @param <T> the type of elements of the concatenated node.
+     * @return a concatenated node if the size of the list is > 1. If the size is 0 then an
+     * empty node is returned (see {@link #emptyNode()}). If the size is 1 then the single
+     * node contained in the list is returned.
+     */
+    @SafeVarargs
+    public static<T> Node<T> node(Node<T>... nodes) {
+        Objects.requireNonNull(nodes);
+        if (nodes.length > 1) {
+            return new ConcNode(nodes);
+        }
+        else if (nodes.length == 1) {
+            return nodes[0];
+        }
+        else {
+            return emptyNode();
+        }
+    }
+
+    /**
+     * Created a truncated (reference ){@link Node} from an input {@link Node}.
+     *
+     * @param n the input node.
+     * @param from the offset from which to truncate from
+     * @param to the offset form which to truncate up to (but not including)
+     * @param generator the array factory
+     * @param <T> the type of elements of the input node and truncated node.
+     * @return a truncated node.
+     */
     public static<T> Node<T> truncateNode(Node<T> n, long from, long to, IntFunction<T[]> generator) {
         long size = truncatedSize(n.count(), from, to);
         if (size == 0)
@@ -189,24 +258,28 @@
     }
 
     /**
-     * Make a fixed size node builder of known size, unless the size is negative, in which case make a variable size
-     * node builder.
+     * Create a (reference) {@link Node.Builder}.
      *
-     *
-     * @param size the known size, or -1 if the size is not known.
-     * @return the node builder.
+     * @param exactSizeIfKnown if >=0 then a builder will be created that has a fixed capacity of exactly
+     *                         exactSizeIfKnown elements; if < 0 then the builder has variable capacity.
+     *                         A fixed capacity builder will fail if an element is added and the builder has reached
+     *                         capacity.
+     * @param generator the array factory.
+     * @param <T> the type of elements of the node builder.
+     * @return a {@code Node.Builder}
      */
-    public static <T> Node.Builder<T> makeBuilder(long size, IntFunction<T[]> generator) {
-        return (size >= 0 && size < Streams.MAX_ARRAY_SIZE) ? makeFixedSizeBuilder(size, generator)
-                                                            : makeVariableSizeBuilder();
+    public static <T> Node.Builder<T> makeBuilder(long exactSizeIfKnown, IntFunction<T[]> generator) {
+        return (exactSizeIfKnown >= 0 && exactSizeIfKnown < Streams.MAX_ARRAY_SIZE)
+               ? makeFixedSizeBuilder(exactSizeIfKnown, generator)
+               : makeVariableSizeBuilder();
     }
 
     /**
-     * Make a fixed size builder.
-     *
+     * Create a fixed size (reference) {@link Node.Builder}.
      *
      * @param size the fixed size of the builder.
-     * @return the node builder.
+     * @param <T> the type of elements of the node builder.
+     * @return a {@code Node.Builder}
      */
     public static <T> Node.Builder<T> makeFixedSizeBuilder(long size, IntFunction<T[]> generator) {
         assert size < Streams.MAX_ARRAY_SIZE;
@@ -214,35 +287,52 @@
     }
 
     /**
-     * Make a variable size node builder.
+     * Create a variable size (reference) @{link Node.Builder}.
      *
-     * @return the node builder.
+     * @param <T> the type of elements of the node builder.
+     * @return a {@code Node.Builder}
      */
     public static <T> Node.Builder<T> makeVariableSizeBuilder() {
         return new SpinedNodeBuilder<>();
     }
 
-    @SafeVarargs
-    public static<T> Node<T> node(Node<T>... nodes) {
-        Objects.requireNonNull(nodes);
-        if (nodes.length < 2) {
-            // @@@ The signature could be (Node<T> n1, Node<T> n2, Node<T>... rest)
-            //     but requires more work to create the final array
-            throw new IllegalArgumentException("The number of nodes must be > 1");
-        }
-        return new ConcNode<>(nodes);
-    }
-
     // Int nodes
 
+    /**
+     * Create an empty {@link Node.OfInt}.
+     *
+     * @return an empty node.
+     */
     public static Node.OfInt emptyIntNode() {
         return EMPTY_INT_NODE;
     }
 
-    public static Node.OfInt intNode(final int[] array) {
+    /**
+     * Create a {@link Node.OfInt} whose contents is an int[] array.
+     * <p>
+     * The created node will hold the reference to the array and will not make
+     * a copy.
+     *
+     * @param array the array.
+     * @return a node holding an array.
+     */
+    public static Node.OfInt intNode(int[] array) {
         return new IntArrayNode(array);
     }
 
+    /**
+     * Create a concatenated {@link Node.OfInt} that has two or more children.
+     * <p>The count of the concatenated node is equal to the sum
+     * of the count of each child. Traversal of the concatenated node
+     * traverses the content of each child in encounter order of the list of children.
+     * Splitting a spliterator obtained from the concatenated node preserves
+     * the encounter order of the list of children.
+     *
+     * @param nodes the list of child nodes.
+     * @return a concatenated node if the size of the list is > 1. If the size is 0 then an
+     * empty node is returned (see {@link #emptyNode()}). If the size is 1 then the single
+     * node contained in the list is returned.
+     */
     @SafeVarargs
     public static Node.OfInt intNode(Node.OfInt... nodes) {
         Objects.requireNonNull(nodes);
@@ -257,6 +347,14 @@
         }
     }
 
+    /**
+     * Created a truncated {@link Node.OfInt} from an input {@link Node.OfInt}.
+     *
+     * @param n the input node.
+     * @param from the offset from which to truncate from
+     * @param to the offset form which to truncate up to (but not including)
+     * @return a truncated node.
+     */
     public static Node.OfInt truncateIntNode(Node.OfInt n, long from, long to) {
         long size = truncatedSize(n.count(), from, to);
         if (size == 0)
@@ -272,22 +370,25 @@
     }
 
     /**
-     * Make a fixed size node builder of known size, unless the size is negative, in which case make a variable size
-     * node builder.
+     * Create a (reference) {@link Node.Builder.OfInt}.
      *
-     * @param size the known size, or -1 if the size is not known.
-     * @return the node builder.
+     * @param exactSizeIfKnown if >=0 then a builder will be created that has a fixed capacity of exactly
+     *                         exactSizeIfKnown elements; if < 0 then the builder has variable capacity.
+     *                         A fixed capacity builder will fail if an element is added and the builder has reached
+     *                         capacity.
+     * @return a {@code Node.Builder.OfInt}
      */
-    public static Node.Builder.OfInt intMakeBuilder(long size) {
-        return (size >= 0 && size < Streams.MAX_ARRAY_SIZE) ? intMakeFixedSizeBuilder(size)
-                                                            : intMakeVariableSizeBuilder();
+    public static Node.Builder.OfInt intMakeBuilder(long exactSizeIfKnown) {
+        return (exactSizeIfKnown >= 0 && exactSizeIfKnown < Streams.MAX_ARRAY_SIZE)
+               ? intMakeFixedSizeBuilder(exactSizeIfKnown)
+               : intMakeVariableSizeBuilder();
     }
 
     /**
-     * Make a fixed size builder.
+     * Create a fixed size {@link Node.Builder.OfInt}.
      *
      * @param size the fixed size of the builder.
-     * @return the node builder.
+     * @return a {@code Node.Builder.OfInt}
      */
     public static Node.Builder.OfInt intMakeFixedSizeBuilder(long size) {
         assert size < Streams.MAX_ARRAY_SIZE;
@@ -295,9 +396,9 @@
     }
 
     /**
-     * Make a variable size node builder.
+     * Create a variable size @{link Node.Builder.OfInt}.
      *
-     * @return the node builder.
+     * @return a {@code Node.Builder.OfInt}
      */
     public static Node.Builder.OfInt intMakeVariableSizeBuilder() {
         return new IntSpinedNodeBuilder();
@@ -305,14 +406,41 @@
 
     // Long nodes
 
+    /**
+     * Create an empty {@link Node.OfLong}.
+     *
+     * @return an empty node.
+     */
     public static Node.OfLong emptyLongNode() {
         return EMPTY_LONG_NODE;
     }
 
+    /**
+     * Create a {@link Node.OfLong} whose contents is a long[] array.
+     * <p>
+     * The created node will hold the reference to the array and will not make
+     * a copy.
+     *
+     * @param array the array.
+     * @return a node holding an array.
+     */
     public static Node.OfLong longNode(final long[] array) {
         return new LongArrayNode(array);
     }
 
+    /**
+     * Create a concatenated {@link Node.OfLong} that has two or more children.
+     * <p>The count of the concatenated node is equal to the sum
+     * of the count of each child. Traversal of the concatenated node
+     * traverses the content of each child in encounter order of the list of children.
+     * Splitting a spliterator obtained from the concatenated node preserves
+     * the encounter order of the list of children.
+     *
+     * @param nodes the list of child nodes.
+     * @return a concatenated node if the size of the list is > 1. If the size is 0 then an
+     * empty node is returned (see {@link #emptyNode()}). If the size is 1 then the single
+     * node contained in the list is returned.
+     */
     @SafeVarargs
     public static Node.OfLong longNode(Node.OfLong... nodes) {
         Objects.requireNonNull(nodes);
@@ -327,6 +455,14 @@
         }
     }
 
+    /**
+     * Created a truncated {@link Node.OfLong} from an input {@link Node.OfLong}.
+     *
+     * @param n the input node.
+     * @param from the offset from which to truncate from
+     * @param to the offset form which to truncate up to (but not including)
+     * @return a truncated node.
+     */
     public static Node.OfLong truncateLongNode(Node.OfLong n, long from, long to) {
         long size = truncatedSize(n.count(), from, to);
         if (size == 0)
@@ -342,22 +478,25 @@
     }
 
     /**
-     * Make a fixed size node builder of known size, unless the size is negative, in which case make a variable size
-     * node builder.
+     * Create a (reference) {@link Node.Builder.OfLong}.
      *
-     * @param size the known size, or -1 if the size is not known.
-     * @return the node builder.
+     * @param exactSizeIfKnown if >=0 then a builder will be created that has a fixed capacity of exactly
+     *                         exactSizeIfKnown elements; if < 0 then the builder has variable capacity.
+     *                         A fixed capacity builder will fail if an element is added and the builder has reached
+     *                         capacity.
+     * @return a {@code Node.Builder.OfLong}
      */
-    public static Node.Builder.OfLong longMakeBuilder(long size) {
-        return (size >= 0 && size < Streams.MAX_ARRAY_SIZE) ? longMakeFixedSizeBuilder(size)
-                                                            : longMakeVariableSizeBuilder();
+    public static Node.Builder.OfLong longMakeBuilder(long exactSizeIfKnown) {
+        return (exactSizeIfKnown >= 0 && exactSizeIfKnown < Streams.MAX_ARRAY_SIZE)
+               ? longMakeFixedSizeBuilder(exactSizeIfKnown)
+               : longMakeVariableSizeBuilder();
     }
 
     /**
-     * Make a fixed size builder.
+     * Create a fixed size {@link Node.Builder.OfLong}.
      *
      * @param size the fixed size of the builder.
-     * @return the node builder.
+     * @return a {@code Node.Builder.OfLong}
      */
     public static Node.Builder.OfLong longMakeFixedSizeBuilder(long size) {
         assert size < Streams.MAX_ARRAY_SIZE;
@@ -365,9 +504,9 @@
     }
 
     /**
-     * Make a variable size node builder.
+     * Create a variable size @{link Node.Builder.OfLong}.
      *
-     * @return the node builder.
+     * @return a {@code Node.Builder.OfLong}
      */
     public static Node.Builder.OfLong longMakeVariableSizeBuilder() {
         return new LongSpinedNodeBuilder();
@@ -375,14 +514,41 @@
 
     // Double nodes
 
+    /**
+     * Create an empty {@link Node.OfDouble}.
+     *
+     * @return an empty node.
+     */
     public static Node.OfDouble emptyDoubleNode() {
         return EMPTY_DOUBLE_NODE;
     }
 
+    /**
+     * Create a {@link Node.OfDouble} whose contents is a double[] array.
+     * <p>
+     * The created node will hold the reference to the array and will not make
+     * a copy.
+     *
+     * @param array the array.
+     * @return a node holding an array.
+     */
     public static Node.OfDouble doubleNode(final double[] array) {
         return new DoubleArrayNode(array);
     }
 
+    /**
+     * Create a concatenated {@link Node.OfDouble} that has two or more children.
+     * <p>The count of the concatenated node is equal to the sum
+     * of the count of each child. Traversal of the concatenated node
+     * traverses the content of each child in encounter order of the list of children.
+     * Splitting a spliterator obtained from the concatenated node preserves
+     * the encounter order of the list of children.
+     *
+     * @param nodes the list of child nodes.
+     * @return a concatenated node if the size of the list is > 1. If the size is 0 then an
+     * empty node is returned (see {@link #emptyNode()}). If the size is 1 then the single
+     * node contained in the list is returned.
+     */
     @SafeVarargs
     public static Node.OfDouble doubleNode(Node.OfDouble... nodes) {
         Objects.requireNonNull(nodes);
@@ -397,6 +563,14 @@
         }
     }
 
+    /**
+     * Created a truncated {@link Node.OfDouble} from an input {@link Node.OfDouble}.
+     *
+     * @param n the input node.
+     * @param from the offset from which to truncate from
+     * @param to the offset form which to truncate up to (but not including)
+     * @return a truncated node.
+     */
     public static Node.OfDouble truncateDoubleNode(Node.OfDouble n, long from, long to) {
         long size = truncatedSize(n.count(), from, to);
         if (size == 0)
@@ -412,22 +586,25 @@
     }
 
     /**
-     * Make a fixed size node builder of known size, unless the size is negative, in which case make a variable size
-     * node builder.
+     * Create a (reference) {@link Node.Builder.OfDouble}.
      *
-     * @param size the known size, or -1 if the size is not known.
-     * @return the node builder.
+     * @param exactSizeIfKnown if >=0 then a builder will be created that has a fixed capacity of exactly
+     *                         exactSizeIfKnown elements; if < 0 then the builder has variable capacity.
+     *                         A fixed capacity builder will fail if an element is added and the builder has reached
+     *                         capacity.
+     * @return a {@code Node.Builder.OfDouble}
      */
-    public static Node.Builder.OfDouble doubleMakeBuilder(long size) {
-        return (size >= 0 && size < Streams.MAX_ARRAY_SIZE) ? doubleMakeFixedSizeBuilder(size)
-                                                            : doubleMakeVariableSizeBuilder();
+    public static Node.Builder.OfDouble doubleMakeBuilder(long exactSizeIfKnown) {
+        return (exactSizeIfKnown >= 0 && exactSizeIfKnown < Streams.MAX_ARRAY_SIZE)
+               ? doubleMakeFixedSizeBuilder(exactSizeIfKnown)
+               : doubleMakeVariableSizeBuilder();
     }
 
     /**
-     * Make a fixed size builder.
+     * Create a fixed size {@link Node.Builder.OfDouble}.
      *
      * @param size the fixed size of the builder.
-     * @return the node builder.
+     * @return a {@code Node.Builder.OfDouble}
      */
     public static Node.Builder.OfDouble doubleMakeFixedSizeBuilder(long size) {
         assert size < Streams.MAX_ARRAY_SIZE;
@@ -435,15 +612,15 @@
     }
 
     /**
-     * Make a variable size node builder.
+     * Create a variable size @{link Node.Builder.OfDouble}.
      *
-     * @return the node builder.
+     * @return a {@code Node.Builder.OfDouble}
      */
     public static Node.Builder.OfDouble doubleMakeVariableSizeBuilder() {
         return new DoubleSpinedNodeBuilder();
     }
 
-    //
+    // Implementations
 
     private static final Node EMPTY_NODE = new EmptyNode();
 
@@ -981,7 +1158,9 @@
     //
 
     private static final int[] EMPTY_INT_ARRAY = new int[0];
+
     private static final long[] EMPTY_LONG_ARRAY = new long[0];
+
     private static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
 
     private static final Node.OfInt EMPTY_INT_NODE = new EmptyIntNode();
--- a/src/share/classes/java/util/stream/PipelineHelper.java	Wed Feb 13 18:37:46 2013 -0800
+++ b/src/share/classes/java/util/stream/PipelineHelper.java	Thu Feb 14 15:05:20 2013 +0100
@@ -64,7 +64,7 @@
 
     /**
      * Get the combined stream and operation flags for the output of the pipeline.  This will incorporate
-     * stream flags from the stream source and all the intermediate operations, but not the terminal operation.
+     * stream flags from the stream source, all the intermediate operations and the terminal operation.
      *
      * @return the combined stream and operation flags for the output of the pipeline
      * @see StreamOpFlag
@@ -72,12 +72,14 @@
     int getStreamAndOpFlags();
 
     /**
-     * Get the operation flags for the terminal or stateful operation that follows the last intermediate
-     * operation described by this {@code PipelineHelper}.
+     * Get the operation flags for the terminal operation.
      *
      * @return the operation flags for the terminal operation.
      * @see StreamOpFlag
      */
+    // @@@ Specifying this concisely is somewhat complicated since since the actual terminal operation flags
+    //     are masked by StreamOpFlag.UPSTREAM_TERMINAL_OP_MASK as the flags propagate upstream through parallel
+    //     pipeline chunks
     int getTerminalOpFlags();
 
     /**