changeset 7541:e27acedff205

First go at docs on Streams and lazy/non-lazy spliterators of sources.
author psandoz
date Wed, 27 Feb 2013 17:46:27 +0100
parents 9619ab4afc70
children b3e0b5001b69
files src/share/classes/java/util/stream/Streams.java src/share/classes/java/util/stream/package-info.java
diffstat 2 files changed, 414 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/stream/Streams.java	Wed Feb 27 12:16:39 2013 +0100
+++ b/src/share/classes/java/util/stream/Streams.java	Wed Feb 27 17:46:27 2013 +0100
@@ -40,124 +40,345 @@
 import java.util.function.UnaryOperator;
 
 /**
- * Streams
+ * This class contains various methods that operate on and/or return instances of {@link Stream},
+ * as well as the primitive specializations {@link IntStream}, {@link LongStream}, and {@link DoubleStream}.
  *
  * @since 1.8
  */
-public class Streams {
+public final class Streams {
 
     private Streams() {
         throw new Error("no instances");
     }
 
-    public static final long MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+    /**
+     * The maximum size of array to allocate.
+     */
+    static final long MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
 
     // Stream construction
 
+    /**
+     * Creates an empty stream.
+     *
+     * @param <T> Type of elements
+     * @return An empty stream
+     */
     public static<T> Stream<T> emptyStream() {
         return stream(Spliterators.<T>emptySpliterator());
     }
 
+    /**
+     * Creates a new sequential stream whose source is a {@code Supplier} of a non-lazy {@code Spliterator}.
+     * <p>
+     * The non-lazy {@code Spliterator} is obtained from the {@code Supplier} when the terminal operation of the stream
+     * pipeline commences.  See <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Supplier} of a {@code Spliterator}
+     * @param characteristics Characteristics of the supplied {@code Spliterator}. The characteristics
+     *                        must be equal to {@code source.get().getCharacteristics()}
+     * @param <T> Type of elements
+     * @return A new stream
+     */
     public static<T> Stream<T> stream(Supplier<? extends Spliterator<T>> source, int characteristics) {
         Objects.requireNonNull(source);
         return new ReferencePipeline<>(source,
                                        StreamOpFlag.fromCharacteristics(characteristics) & ~StreamOpFlag.IS_PARALLEL);
     }
 
+    /**
+     * Creates a new parallel stream whose source is a {@code Supplier} of a non-lazy {@code Spliterator}.
+     * <p>
+     * The non-lazy {@code Spliterator} is obtained from the {@code Supplier} when the terminal operation of the stream
+     * pipeline commences.  See <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Supplier} of a {@code Spliterator}
+     * @param characteristics Characteristics of the supplied {@code Spliterator}. The characteristics
+     *                        must be equal to {@code source.get().getCharacteristics()}
+     * @param <T> Type of elements
+     * @return A new stream
+     */
     public static<T> Stream<T> parallelStream(Supplier<? extends Spliterator<T>> source, int characteristics) {
         Objects.requireNonNull(source);
         return new ReferencePipeline<>(source,
                                        StreamOpFlag.fromCharacteristics(characteristics) | StreamOpFlag.IS_PARALLEL);
     }
 
+    /**
+     * Creates a new sequential stream whose source is a lazy {@code Spliterator}.
+     * <p>
+     * The {@code Spliterator} must be <b>lazy</b> and not commit to the sequence of elements it covers until it is
+     * invoked with a method that requires the sequence of elements be known, for example when the size estimate is
+     * required or when traversal occurs, but not when the characteristics are required.  See
+     * <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Spliterator}
+     * @param <T> Type of elements
+     * @return A new stream
+     */
     public static<T> Stream<T> stream(Spliterator<T> source) {
         return stream(() -> source, source.characteristics());
     }
 
+    /**
+     * Creates a new parallel stream whose source is a lazy {@code Spliterator}.
+     * <p>
+     * The {@code Spliterator} must be <b>lazy</b> and not commit to the sequence of elements it covers until it is
+     * invoked with a method that requires the sequence of elements be known, for example when the size estimate is
+     * required or when traversal occurs, but not when the characteristics are required.  See
+     * <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Spliterator}
+     * @param <T> Type of elements
+     * @return A new stream
+     */
     public static<T> Stream<T> parallelStream(Spliterator<T> source) {
         return parallelStream(() -> source, source.characteristics());
     }
 
     // IntStream construction
 
+    /**
+     * Creates an empty {@code int} stream.
+     *
+     * @return An empty {@code int} stream
+     */
     public static IntStream emptyIntStream() {
         return intStream(Spliterators.emptyIntSpliterator());
     }
 
+    /**
+     * Creates a new sequential {@code int} stream whose source is a {@code Supplier} of a non-lazy
+     * {@code Spliterator.OfInt}.
+     * <p>
+     * The non-lazy {@code Spliterator.OfInt} is obtained from the {@code Supplier} when the terminal operation of the
+     * stream pipeline commences.  See <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Supplier} of a {@code Spliterator.OfInt}
+     * @param characteristics Characteristics of the supplied {@code Spliterator.OfInt}. The characteristics
+     *                        must be equal to {@code source.get().getCharacteristics()}
+     * @return A new {@code int} stream
+     */
     public static IntStream intStream(Supplier<? extends Spliterator.OfInt> source, int characteristics) {
         return new IntPipeline<>(source,
                                  StreamOpFlag.fromCharacteristics(characteristics) & ~StreamOpFlag.IS_PARALLEL);
     }
 
+    /**
+     * Creates a new parallel {@code int} stream whose source is a {@code Supplier} of a non-lazy
+     * {@code Spliterator.OfInt}.
+     * <p>
+     * The non-lazy {@code Spliterator.OfInt} is obtained from the {@code Supplier} when the terminal operation of the
+     * stream pipeline commences.  See <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Supplier} of a {@code Spliterator.OfInt}
+     * @param characteristics Characteristics of the supplied {@code Spliterator.OfInt}. The characteristics
+     *                        must be equal to {@code source.get().getCharacteristics()}
+     * @return A new {@code int} stream
+     */
     public static IntStream intParallelStream(Supplier<? extends Spliterator.OfInt> source, int characteristics) {
         return new IntPipeline<>(source,
                                  StreamOpFlag.fromCharacteristics(characteristics) | StreamOpFlag.IS_PARALLEL);
     }
 
+    /**
+     * Creates a new sequential {@code int} stream whose source is a lazy {@code Spliterator.OfInt}.
+     * <p>
+     * The {@code Spliterator.OfInt} must be <b>lazy</b> and not commit to the sequence of elements it covers until it
+     * is invoked with a method that requires the sequence of elements be known, for example when the size estimate is
+     * required or when traversal occurs, but not when the characteristics are required.  See
+     * <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Spliterator.OfInt}
+     * @return A new {@code int} stream
+     */
     public static IntStream intStream(Spliterator.OfInt source) {
         return intStream(() -> source, source.characteristics());
     }
 
+    /**
+     * Creates a new parallel {@code int} stream whose source is a lazy {@code Spliterator.OfInt}.
+     * <p>
+     * The {@code Spliterator.OfInt} must be <b>lazy</b> and not commit to the sequence of elements it covers until it
+     * is invoked with a method that requires the sequence of elements be known, for example when the size estimate is
+     * required or when traversal occurs, but not when the characteristics are required.  See
+     * <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Spliterator.OfInt}
+     * @return A new {@code int} stream
+     */
     public static IntStream intParallelStream(Spliterator.OfInt source) {
         return intParallelStream(() -> source, source.characteristics());
     }
 
     // LongStream construction
 
+    /**
+     * Creates an empty {@code long} stream.
+     *
+     * @return An empty {@code long} stream
+     */
     public static LongStream emptyLongStream() {
         return longStream(Spliterators.emptyLongSpliterator());
     }
 
+    /**
+     * Creates a new sequential {@code long} stream whose source is a {@code Supplier} of a non-lazy
+     * {@code Spliterator.OfLong}.
+     * <p>
+     * The non-lazy {@code Spliterator.OfLong} is obtained from the {@code Supplier} when the terminal operation of the
+     * stream pipeline commences.  See <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Supplier} of a {@code Spliterator.OfLong}
+     * @param characteristics Characteristics of the supplied {@code Spliterator.OfLong}. The characteristics
+     *                        must be equal to {@code source.get().getCharacteristics()}
+     * @return A new {@code long} stream
+     */
     public static LongStream longStream(Supplier<? extends Spliterator.OfLong> source, int characteristics) {
         return new LongPipeline<>(source,
                                   StreamOpFlag.fromCharacteristics(characteristics) & ~StreamOpFlag.IS_PARALLEL);
     }
 
+    /**
+     * Creates a new parallel {@code long} stream whose source is a {@code Supplier} of a non-lazy
+     * {@code Spliterator.OfLong}.
+     * <p>
+     * The non-lazy {@code Spliterator.OfLong} is obtained from the {@code Supplier} when the terminal operation of the
+     * stream pipeline commences.  See <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Supplier} of a {@code Spliterator.OfLong}
+     * @param characteristics Characteristics of the supplied {@code Spliterator.OfLong}. The characteristics
+     *                        must be equal to {@code source.get().getCharacteristics()}
+     * @return A new {@code long} stream
+     */
     public static LongStream longParallelStream(Supplier<? extends Spliterator.OfLong> source, int characteristics) {
         return new LongPipeline<>(source,
                                   StreamOpFlag.fromCharacteristics(characteristics) | StreamOpFlag.IS_PARALLEL);
     }
 
+    /**
+     * Creates a new sequential {@code long} stream whose source is a lazy {@code Spliterator.OfLong}.
+     * <p>
+     * The {@code Spliterator.OfLong} must be <b>lazy</b> and not commit to the sequence of elements it covers until it
+     * is invoked with a method that requires the sequence of elements be known, for example when the size estimate is
+     * required or when traversal occurs, but not when the characteristics are required.  See
+     * <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Spliterator.OfLong}
+     * @return A new {@code long} stream
+     */
     public static LongStream longStream(Spliterator.OfLong source) {
         return longStream(() -> source, source.characteristics());
     }
 
+    /**
+     * Creates a new parallel {@code long} stream whose source is a lazy {@code Spliterator.OfLong}.
+     * <p>
+     * The {@code Spliterator.OfLong} must be <b>lazy</b> and not commit to the sequence of elements it covers until it
+     * is invoked with a method that requires the sequence of elements be known, for example when the size estimate is
+     * required or when traversal occurs, but not when the characteristics are required.  See
+     * <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Spliterator.OfLong}
+     * @return A new {@code long} stream
+     */
     public static LongStream longParallelStream(Spliterator.OfLong source) {
         return longParallelStream(() -> source, source.characteristics());
     }
 
     // DoubleStream construction
 
+    /**
+     * Creates an empty {@code double} stream.
+     *
+     * @return An empty {@code double} stream
+     */
     public static DoubleStream emptyDoubleStream() {
         return doubleStream(Spliterators.emptyDoubleSpliterator());
     }
 
-    public static DoubleStream doubleStream(Supplier<? extends Spliterator.OfDouble> source, int characteristics) {
+    /**
+     * Creates a new sequential {@code double} stream whose source is a {@code Supplier} of a non-lazy
+     * {@code Spliterator.OfDouble}.
+     * <p>
+     * The non-lazy {@code Spliterator.OfDouble} is obtained from the {@code Supplier} when the terminal operation of
+     * the stream pipeline commences.  See <a href="package-summary.html#StreamSources">Stream sources</a> for more
+     * details.
+     *
+     * @param source A {@code Supplier} of a {@code Spliterator.OfDouble}
+     * @param characteristics Characteristics of the supplied {@code Spliterator.OfDouble}. The characteristics
+     *                        must be equal to {@code source.get().getCharacteristics()}
+     * @return A new {@code double} stream
+     */
+    public static DoubleStream doubleStream(Supplier<? extends Spliterator.OfDouble> source,
+                                            int characteristics) {
         return new DoublePipeline<>(source,
                                     StreamOpFlag.fromCharacteristics(characteristics) & ~StreamOpFlag.IS_PARALLEL);
     }
 
-    public static DoubleStream doubleParallelStream(Supplier<? extends Spliterator.OfDouble> source, int characteristics) {
+    /**
+     * Creates a new parallel {@code double} stream whose source is a {@code Supplier} of a non-lazy
+     * {@code Spliterator.OfDouble}.
+     * <p>
+     * The non-lazy {@code Spliterator.OfDouble} is obtained from the {@code Supplier} when the terminal operation of
+     * the stream pipeline commences.  See <a href="package-summary.html#StreamSources">Stream sources</a> for more
+     * details.
+     *
+     * @param source A {@code Supplier} of a {@code Spliterator.OfDouble}
+     * @param characteristics Characteristics of the supplied {@code Spliterator.OfDouble}. The characteristics
+     *                        must be equal to {@code source.get().getCharacteristics()}
+     * @return A new {@code double} stream
+     */
+    public static DoubleStream doubleParallelStream(Supplier<? extends Spliterator.OfDouble> source,
+                                                    int characteristics) {
         return new DoublePipeline<>(source,
                                     StreamOpFlag.fromCharacteristics(characteristics) | StreamOpFlag.IS_PARALLEL);
     }
 
+    /**
+     * Creates a new sequential {@code double} stream whose source is a lazy {@code Spliterator.OfDouble}.
+     * <p>
+     * The {@code Spliterator.OfDouble} must be <b>lazy</b> and not commit to the sequence of elements it covers until
+     * it is invoked with a method that requires the sequence of elements be known, for example when the size estimate
+     * is required or when traversal occurs, but not when the characteristics are required.  See
+     * <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Spliterator.OfDouble}
+     * @return A new {@code double} stream
+     */
     public static DoubleStream doubleStream(Spliterator.OfDouble source) {
         return doubleStream(() -> source, source.characteristics());
     }
 
+    /**
+     * Creates a new parallel {@code double} stream whose source is a lazy {@code Spliterator.OfDouble}.
+     * <p>
+     * The {@code Spliterator.OfDouble} must be <b>lazy</b> and not commit to the sequence of elements it covers until
+     * it is invoked with a method that requires the sequence of elements be known, for example when the size estimate
+     * is required or when traversal occurs, but not when the characteristics are required.  See
+     * <a href="package-summary.html#StreamSources">Stream sources</a> for more details.
+     *
+     * @param source A {@code Spliterator.OfDouble}
+     * @return A new {@code double} stream
+     */
     public static DoubleStream doubleParallelStream(Spliterator.OfDouble source) {
         return doubleParallelStream(() -> source, source.characteristics());
     }
 
-    // Empty iterators and spliterators
+    // Infinite Stream generators
 
-    // Iterators from spliterators
-
-    // Spliterators from iterators
-
-    // Infinite stream generators
-
+    /**
+     * Creates a sequential stream that is an infinite sequence of elements.  The first element is {@code seed}, the
+     * second element is the result of applying {@code seed} to the function {@code f}, and the nth element is the
+     * result of applying the nth minus one element to the function {@code f}.
+     * <p>
+     * To transform into a parallel stream call the {@code parallel()} method on the created stream.
+     *
+     * @param seed The first element in sequence
+     * @param f The function to be applied to the nth minus one element to produce the nth element, where n > 1
+     * @param <T> The type of elements
+     * @return A stream that is an infinite sequence of elements
+     */
     public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
         Objects.requireNonNull(f);
         final InfiniteIterator<T> iterator = new InfiniteIterator<T>() {
@@ -171,11 +392,38 @@
         return stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED));
     }
 
-    public static<T> Stream<T> generate(Supplier<T> f) {
-        InfiniteIterator<T> iterator = f::get;
+    /**
+     * Creates a sequential stream that is an infinite sequence of supplied elements.  Each element is supplied in
+     * sequence order.
+     * <p>
+     * A {@code Supplier} can supply constant values, such as {@code () -> "CONSTANT"}, or can supply non-constant
+     * values in which case the {@code Supplier} may have side-effects.
+     * <p>
+     * To transform into a parallel stream call the {@code parallel()} method on the created stream.
+     *
+     * @param s the {@code Supplier} of elements; may have side-effects.  The {@code Supplier} will not be invoked
+     *          concurrently so it need not protect access to mutable state.
+     * @param <T> The type of elements
+     * @return A stream that is an infinite sequence of elements
+     */
+    public static<T> Stream<T> generate(Supplier<T> s) {
+        InfiniteIterator<T> iterator = s::get;
         return stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED));
     }
 
+    // Infinite IntStream generators and ranges
+
+    /**
+     * Creates a sequential {@code int} stream that is an infinite sequence of {@code int} elements.  The first element
+     * is {@code seed}, the second element is the result of applying {@code seed} to the function {@code f}, and the
+     * nth element is the result of applying the nth minus one element to the function {@code f}.
+     * <p>
+     * To transform into a parallel stream call the {@code parallel()} method on the created stream.
+     *
+     * @param seed The first {@code int} element in sequence
+     * @param f The function to be applied to the nth minus one element to produce the nth element, where n > 1
+     * @return An {@code int} stream that is an infinite sequence of {@code int} elements
+     */
     public static IntStream iterateInt(final int seed, final IntUnaryOperator f) {
         Objects.requireNonNull(f);
         final InfiniteIterator.OfInt iterator = new InfiniteIterator.OfInt() {
@@ -191,8 +439,21 @@
         return intStream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED));
     }
 
-    public static IntStream generateInt(IntSupplier f) {
-        InfiniteIterator.OfInt iterator = f::getAsInt;
+    /**
+     * Creates a sequential {@code int} stream that is an infinite sequence of supplied {@code int} elements.  Each
+     * element is supplied in sequence order.
+     * <p>
+     * A {@code IntSupplier} can supply constant values, such as {@code () -> 123}, or can supply non-constant
+     * values in which case the {@code IntSupplier} may have side-effects.
+     * <p>
+     * To transform into a parallel stream call the {@code parallel()} method on the created stream.
+     *
+     * @param s the {@code IntSupplier} of elements; may have side-effects.  The {@code IntSupplier} will not be invoked
+     *          concurrently so it need not protect access to mutable state.
+     * @return An {@code int} stream that is an infinite sequence of {@code int} elements
+     */
+    public static IntStream generateInt(IntSupplier s) {
+        InfiniteIterator.OfInt iterator = s::getAsInt;
         return intStream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED));
     }
 
@@ -254,6 +515,19 @@
         return intStream(new RangeIntSpliterator(start, end, step));
     }
 
+    // Infinite LongStream generators and ranges
+
+    /**
+     * Creates a sequential {@code long} stream that is an infinite sequence of {@code long} elements.  The first
+     * element is {@code seed}, the second element is the result of applying {@code seed} to the function {@code f}, and
+     * the nth element is the result of applying the nth minus one element to the function {@code f}.
+     * <p>
+     * To transform into a parallel stream call the {@code parallel()} method on the created stream.
+     *
+     * @param seed The first {@code long} element in sequence
+     * @param f The function to be applied to the nth minus one element to produce the nth element, where n > 1
+     * @return A {@code long} stream that is an infinite sequence of {@code long} elements
+     */
     public static LongStream iterateLong(final long seed, final LongUnaryOperator f) {
         Objects.requireNonNull(f);
         final InfiniteIterator.OfLong iterator = new InfiniteIterator.OfLong() {
@@ -269,8 +543,21 @@
         return longStream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED));
     }
 
-    public static LongStream generateLong(LongSupplier f) {
-        InfiniteIterator.OfLong iterator = f::getAsLong;
+    /**
+     * Creates a sequential {@code long} stream that is an infinite sequence of supplied {@code long} elements.  Each
+     * element is supplied in sequence order.
+     * <p>
+     * A {@code LongSupplier} can supply constant values, such as {@code () -> 123L}, or can supply non-constant
+     * values in which case the {@code LongSupplier} may have side-effects.
+     * <p>
+     * To transform into a parallel stream call the {@code parallel()} method on the created stream.
+     *
+     * @param s the {@code LongSupplier} of elements; may have side-effects.  The {@code LongSupplier} will not be
+     *          invoked concurrently so it need not protect access to mutable state.
+     * @return A {@code long} stream that is an infinite sequence of {@code long} elements
+     */
+    public static LongStream generateLong(LongSupplier s) {
+        InfiniteIterator.OfLong iterator = s::getAsLong;
         return longStream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED));
     }
 
@@ -332,6 +619,19 @@
         return longStream(new RangeLongSpliterator(start, end, step));
     }
 
+    // Infinite DoubleStream generators
+
+    /**
+     * Creates a sequential {@code double} stream that is an infinite sequence of {@code double} elements.  The first
+     * element is {@code seed}, the second element is the result of applying {@code seed} to the function {@code f}, and
+     * the nth element is the result of applying the nth minus one element to the function {@code f}.
+     * <p>
+     * To transform into a parallel stream call the {@code parallel()} method on the created stream.
+     *
+     * @param seed The first {@code double} element in sequence
+     * @param f The function to be applied to the nth minus one element to produce the nth element, where n > 1
+     * @return A {@code double} stream that is an infinite sequence of {@code double} elements
+     */
     public static DoubleStream iterateDouble(final double seed, final DoubleUnaryOperator f) {
         Objects.requireNonNull(f);
         final InfiniteIterator.OfDouble iterator = new InfiniteIterator.OfDouble() {
@@ -347,13 +647,39 @@
         return doubleStream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED));
     }
 
-    public static DoubleStream generateDouble(DoubleSupplier f) {
-        InfiniteIterator.OfDouble iterator = f::getAsDouble;
+    /**
+     * Creates a sequential {@code double} stream that is an infinite sequence of supplied {@code double} elements.
+     * Each element is supplied in sequence order.
+     * <p>
+     * A {@code DoubleSupplier} can supply constant values, such as {@code () -> 123.0}, or can supply non-constant
+     * values in which case the {@code DoubleSupplier} may have side-effects.
+     * <p>
+     * To transform into a parallel stream call the {@code parallel()} method on the created stream.
+     *
+     * @param s the {@code DoubleSupplier} of elements; may have side-effects.  The {@code DoubleSupplier} will not be
+     *          invoked concurrently so it need not protect access to mutable state.
+     * @return A {@code double} stream that is an infinite sequence of {@code double} elements
+     */
+    public static DoubleStream generateDouble(DoubleSupplier s) {
+        InfiniteIterator.OfDouble iterator = s::getAsDouble;
         return doubleStream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED));
     }
 
-    // Concat
+    // Stream combining functions
 
+    /**
+     * Creates a concatenated stream whose elements are all the elements, in encounter order if any, of a first stream
+     * proceeded by all the elements of a second stream, in encounter order if any.
+     * <p>
+     * The concatenated stream is lazy and elements are not consumed until the terminal operation is executed.
+     * <p>
+     * To transform into a parallel stream call the {@code parallel()} method on the created stream.
+     *
+     * @param a The first stream
+     * @param b The second stream to concatenate on to end of the first stream
+     * @param <T> Type of elements
+     * @return A concatenated stream
+     */
     public static<T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
         @SuppressWarnings("unchecked")
         Spliterator<T> aSpliterator = (Spliterator<T>) Objects.requireNonNull(a).spliterator();
@@ -433,6 +759,29 @@
                : stream(split);
     }
 
+    /**
+     *
+     * Creates a zipped stream whose elements are the result of combining the elements of two streams, in encounter
+     * order if any.
+     * <p>
+     * The number of elements of the zipped stream will be the smaller of the number of elements of the first or second
+     * stream.
+     * <p>
+     * The zipped stream is lazy and elements are not consumed until the terminal operation is executed. If one stream
+     * is larger than the other then only some of the elements of the larger stream will be consumed, at most the number
+     * of elements consumed will be the same as the total number of elements of the smaller stream.
+     * <p>
+     * To transform into a parallel stream call the {@code parallel()} method on the created stream.
+     *
+     * @param a The first stream to combine
+     * @param b The second stream to combine
+     * @param zipper The function applied to an element from the first stream and an element from the second stream
+     *               to produce an element for the zipped stream
+     * @param <A> The type of elements of the first stream
+     * @param <B> The type of elements of the second stream
+     * @param <C> The type of elements of the zipped stream
+     * @return A zipped stream
+     */
     public static<A, B, C> Stream<C> zip(Stream<? extends A> a,
                                          Stream<? extends B> b,
                                          BiFunction<? super A, ? super B, ? extends C> zipper) {
@@ -474,7 +823,7 @@
                : stream(split);
     }
 
-    // Spliterator implementations
+    // Iterator and Spliterator implementations
 
     private interface InfiniteIterator<T> extends Iterator<T> {
         /** Always returns true */
@@ -490,7 +839,7 @@
         interface OfDouble extends InfiniteIterator<Double>, PrimitiveIterator.OfDouble { }
     }
 
-    private static class RangeIntSpliterator implements Spliterator.OfInt {
+    private static final class RangeIntSpliterator implements Spliterator.OfInt {
         private int from;
         private final int upTo;
         private final int step;
@@ -555,7 +904,7 @@
         }
     }
 
-    private static class RangeLongSpliterator implements Spliterator.OfLong {
+    private static final class RangeLongSpliterator implements Spliterator.OfLong {
         private long from;
         private final long upTo;
         private final long step;
--- a/src/share/classes/java/util/stream/package-info.java	Wed Feb 27 12:16:39 2013 +0100
+++ b/src/share/classes/java/util/stream/package-info.java	Wed Feb 27 17:46:27 2013 +0100
@@ -76,6 +76,47 @@
  * <p>Terminal operations consume the {@code Stream} and produce a result or a side-effect.  After a terminal
  * operation is performed, the stream can no longer be used.
  *
+ * <h3><a name="StreamSources">Stream sources</a></h3>
+ *
+ * <p>A pipeline is initially constructed from a stream source. A stream source supplies a {@code Spliterator} that
+ * covers elements of the source and provides element traversal operations for a possibly-parallel computation.  The
+ * {@code Spliterator} is used to construct the initial {@code Stream} in the pipeline.  See methods on
+ * {@link java.util.stream.Streams} for such construction.
+ *
+ * <p>A source may directly supply a {@code Spliterator}.  If so, that {@code Spliterator} must be <b>lazy</b> and not
+ * commit to the sequence of elements it covers until the terminal operation commences.  More specifically the
+ * {@code Spliterator} must not commit until it is invoked with a method that requires the sequence of elements be
+ * known, for example when the size estimate is required or when traversal occurs.
+ *
+ * <p>If the contents of the source can be and are modified before the point at which the terminal operation commences
+ * then those modifications must be reflected in the covered elements.  After that point, and depending on the
+ * properties of the source, modifications might not be reflected in the covered elements and the throwing of a
+ * {@code ConcurrentModificationException} may occur.
+ *
+ * <p>For example, in the following code a list is created consisting of two strings "one" and "two", a stream is
+ * created from that list, then the list is modified adding a third string "three", finally the elements of the stream
+ * are collected and joined together. Since the list was modified before the terminal {@code collect} operation
+ * commenced the result will be a string of "one two three":
+ * <pre>
+ *     List<String> l = new ArrayList(Arrays.asList("one", "two"));
+ *     Stream<String> sl = l.stream();
+ *     l.add("three");
+ *     String s = sl.collect(toStringJoiner(" ")).toString();
+ * </pre>
+ * However, if the list is modified after the terminal operation commences then a
+ * {@code ConcurrentModificationException} will occur, such as:
+ * <pre>
+ *     List<String> l = new ArrayList(Arrays.asList("one", "two"));
+ *     Stream<String> sl = l.stream();
+ *     String s = sl.peek(s -> l.add("BAD LAMBDA")).collect(toStringJoiner(" ")).toString();
+ * </pre>
+ * Note: the lambda expression in the {@code peek} operation is modifying mutable state, see the section on
+ * <em>Non-interference</em> for further details on the <em>non-interference</em> rules lambda expressions should obey.
+ *
+ * <p>If a source cannot directly supply a lazy {@code Spliterator} then it may do so indirectly using a
+ * {@code Supplier} of a non-lazy {@code Spliterator}.  The {@code Spliterator} will be obtained from the
+ * {@code Supplier} when the terminal operation commences.
+ *
  * <h3><a name="StreamOps">Stream operations</a></h3>
  *
  * <p>Stream operations are divided into two categories: <em>intermediate</em> and <em>terminal</em>.  An