Spec pass on Stream

Brian Goetz brian.goetz at oracle.com
Fri Jul 5 15:03:51 PDT 2013


Here's my latest whack at the interface doc for Stream.  The intent is 
to cover the basic concepts (what is a stream) and the must-describes 
(no interference with source during pipeline execution) here, and then 
link to package doc for more detail.

Ideally I would have liked to @inheritDoc this all from BaseStream to 
{,Int,Long,Double}Stream, but javadoc didn't cooperate, so there would 
likely be cutting and pasting across the five XxxStream interfaces.

/**
  * A sequence of elements supporting sequential and parallel aggregate
  * operations. For example:
  *
  * <pre>{@code
  *     int sum = widgets.stream()
  *                      .filter(b -> b.getColor() == RED)
  *                      .mapToInt(b -> b.getWeight())
  *                      .sum();
  * }</pre>
  *
  * In this example, {@code widgets} is a {@code Collection<Widget>}. 
We create
  * a stream of {@code Widget} objects via {@link Collection#stream 
Collection.stream()},
  * filter it to produce a stream containing only the red widgets, and then
  * transform it into a stream of {@code int} values representing the 
weight of
  * each red widget. Then this stream is summed to produce a total weight.
  *
  * <p>To perform a computation, stream
  * <a href="package-summary.html#StreamOps">operations</a> are composed 
into a
  * <em>stream pipeline</em>.  A stream pipeline consists of a source (which
  * might be an array, a collection, a generator function, an IO channel,
  * etc), zero or more <em>intermediate operations</em> (which transform a
  * stream into another stream, such as {@link 
Stream#filter(Predicate)}), and a
  * <em>terminal operation</em> (which produces a result or side-effect, 
such
  * as {@link IntStream#sum()} or {@link IntStream#forEach(IntConsumer)}).
  * Streams are lazy; computation on the source data is only performed 
when the
  * terminal operation is initiated, and source elements are consumed only
  * as needed.
  *
  * <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
  * provide a means to directly access or manipulate their elements, and are
  * instead concerned with declaratively describing their source and the
  * computational operations which will be performed in aggregate on 
that source.
  * However, if the provided stream operations do not offer the desired
  * functionality, the {@link #iterator()} and {@link #spliterator()} 
operations
  * can be used to perform a controlled traversal.
  *
  * <p>A stream pipeline, like the "widgets" example above, can be viewed as
  * a <em>query</em> on the stream source.  Unless the source was explicitly
  * designed for concurrent modification (such as a {@link 
ConcurrentHashMap}),
  * unpredictable or erroneous behavior may result from modifying the stream
  * source while it is being queried.
  *
  * <p>Most stream operations accept parameters that describe user-specified
  * behavior, such as the lambda expression {@code b -> b.getWeight()} 
passed to
  * {@code mapToInt} in the example above.  Such parameters are always 
instances
  * of a <a href="../function/package-summary.html">functional 
interface</a> such
  * as {@link java.util.function.Function}, and are often lambda 
expressions or
  * method references.  These parameters can never be null, should not 
modify the
  * stream source, and should be
  * <a href="package-summary.html#NonInterference">effectively stateless</a>
  * (their result should not depend on any state that might change during
  * execution of the stream pipeline.)
  *
  * <p>A stream should be operated on (invoke an intermediate or 
terminal stream
  * operation) only once.  This rules out, for example, "forked" 
streams, where
  * the same source feeds two or more pipelines, or multiple traversals 
of the
  * same stream.  A stream implementation may throw {@link 
IllegalStateException}
  * if it detects that the stream is being reused. However, since some 
stream
  * operations may return their receiver rather than a new stream 
object, it may
  * not be possible to detect reuse in all cases.
  *
  * <p>When executed (by initiating its terminal operation), stream 
pipelines may
  * execute either sequentially or in
  * <a href="package-summary.html#Parallelism">parallel</a>.  This
  * execution mode is a property of the stream.  Streams are created
  * with an initial choice of sequential or parallel execution.  (For 
example,
  * {@link Collection#stream() Collection.stream()} creates a sequential 
stream,
  * and {@link Collection#parallelStream() Collection.parallelStream()} 
creates
  * a parallel one.)  The orientation of a stream pipeline may be 
modified by
  * the {@link #sequential()} or {@link #parallel()} methods, and may be 
queried
  * with the {@link #isParallel()} method.  Whether a stream pipeline 
executes in
  * sequential or parallel is determined by the orientation of the stream
  * instance on which the terminal operation is invoked.
  *
  * @param <T> type of stream elements
  * @since 1.8
  * @see <a href="package-summary.html">java.util.stream</a>
  */


More information about the lambda-libs-spec-experts mailing list