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