8011916: Spec update for java.util.stream
8024339: j.u.s.Stream.reduce(BinaryOperator) throws unexpected NPE
Reviewed-by: mduigou
Contributed-by: brian.goetz@oracle.com
--- a/jdk/src/share/classes/java/util/Collection.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/Collection.java Fri Sep 06 22:20:01 2013 -0700
@@ -549,6 +549,7 @@
* @return a {@code Spliterator} over the elements in this collection
* @since 1.8
*/
+ @Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
--- a/jdk/src/share/classes/java/util/function/package-info.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/function/package-info.java Fri Sep 06 22:20:01 2013 -0700
@@ -105,5 +105,6 @@
* </ul>
*
* @see java.lang.FunctionalInterface
+ * @since 1.8
*/
package java.util.function;
--- a/jdk/src/share/classes/java/util/stream/BaseStream.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/BaseStream.java Fri Sep 06 22:20:01 2013 -0700
@@ -24,16 +24,103 @@
*/
package java.util.stream;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collection;
import java.util.Iterator;
import java.util.Spliterator;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.IntConsumer;
+import java.util.function.Predicate;
/**
- * Base interface for stream types such as {@link Stream}, {@link IntStream},
- * etc. Contains methods common to all stream types.
+ * A sequence of elements supporting sequential and parallel aggregate
+ * operations. The following example illustrates an aggregate operation using
+ * {@link Stream} and {@link IntStream}:
+ *
+ * <pre>{@code
+ * int sum = widgets.stream()
+ * .filter(w -> w.getColor() == RED)
+ * .mapToInt(w -> w.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.
*
- * @param <T> type of stream elements
- * @param <S> type of stream implementing {@code BaseStream}
+ * <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 w -> w.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 (invoking 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>Streams have a {@link #close()} method and implement {@link AutoCloseable},
+ * but nearly all stream instances do not actually need to be closed after use.
+ * Generally, only streams whose source is an IO channel (such as those returned
+ * by {@link Files#lines(Path, Charset)}) will require closing. Most streams
+ * are backed by collections, arrays, or generating functions, which require no
+ * special resource management. (If a stream does require closing, it can be
+ * declared as a resource in a {@code try}-with-resources statement.)
+ *
+ * <p>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.) This choice of execution mode may be modified by the
+ * {@link #sequential()} or {@link #parallel()} methods, and may be queried with
+ * the {@link #isParallel()} method.
+ *
+ * @param <T> the type of the stream elements
+ * @param <S> the type of of the stream implementing {@code BaseStream}
* @since 1.8
+ * @see <a href="package-summary.html">java.util.stream</a>
*/
public interface BaseStream<T, S extends BaseStream<T, S>>
extends AutoCloseable {
@@ -58,14 +145,11 @@
Spliterator<T> spliterator();
/**
- * Returns whether this stream, when executed, would execute in parallel
- * (assuming no further modification of the stream, such as appending
- * further intermediate operations or changing its parallelism). Calling
- * this method after invoking an intermediate or terminal stream operation
- * method may yield unpredictable results.
+ * Returns whether this stream, if a terminal operation were to be executed,
+ * would execute in parallel. Calling this method after invoking an
+ * terminal stream operation method may yield unpredictable results.
*
* @return {@code true} if this stream would execute in parallel if executed
- * without further modification otherwise {@code false}
*/
boolean isParallel();
@@ -96,7 +180,8 @@
/**
* Returns an equivalent stream that is
* <a href="package-summary.html#Ordering">unordered</a>. May return
- * itself if the stream was already unordered.
+ * itself, either because the stream was already unordered, or because
+ * the underlying stream state was modified to be unordered.
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
--- a/jdk/src/share/classes/java/util/stream/Collector.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/Collector.java Fri Sep 06 22:20:01 2013 -0700
@@ -26,6 +26,7 @@
import java.util.Collections;
import java.util.EnumSet;
+import java.util.Objects;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
@@ -33,71 +34,74 @@
import java.util.function.Supplier;
/**
- * A <a href="package-summary.html#Reduction">reduction operation</a> that
- * folds input elements into a mutable result container, optionally transforming
+ * A <a href="package-summary.html#Reduction">mutable reduction operation</a> that
+ * accumulates input elements into a mutable result container, optionally transforming
* the accumulated result into a final representation after all input elements
- * have been processed.
+ * have been processed. Reduction operations can be performed either sequentially
+ * or in parallel.
*
* <p>Examples of mutable reduction operations include:
* accumulating elements into a {@code Collection}; concatenating
* strings using a {@code StringBuilder}; computing summary information about
* elements such as sum, min, max, or average; computing "pivot table" summaries
- * such as "maximum valued transaction by seller", etc. Reduction operations
- * can be performed either sequentially or in parallel.
- *
- * <p>The following are examples of using the predefined {@code Collector}
- * implementations in {@link Collectors} with the {@code Stream} API to perform
- * mutable reduction tasks:
- * <pre>{@code
- * // Accumulate names into a List
- * List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());
- *
- * // Accumulate names into a TreeSet
- * Set<String> list = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));
- *
- * // Convert elements to strings and concatenate them, separated by commas
- * String joined = things.stream()
- * .map(Object::toString)
- * .collect(Collectors.joining(", "));
- *
- * // Find highest-paid employee
- * Employee highestPaid = employees.stream()
- * .collect(Collectors.maxBy(Comparators.comparing(Employee::getSalary)))
- * .get();
- *
- * // Group employees by department
- * Map<Department, List<Employee>> byDept
- * = employees.stream()
- * .collect(Collectors.groupingBy(Employee::getDepartment));
- *
- * // Find highest-paid employee by department
- * Map<Department, Optional<Employee>> highestPaidByDept
- * = employees.stream()
- * .collect(Collectors.groupingBy(Employee::getDepartment,
- * Collectors.maxBy(Comparators.comparing(Employee::getSalary))));
- *
- * // Partition students into passing and failing
- * Map<Boolean, List<Student>> passingFailing =
- * students.stream()
- * .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
- *
- * }</pre>
+ * such as "maximum valued transaction by seller", etc. The class {@link Collectors}
+ * provides implementations of many common mutable reductions.
*
* <p>A {@code Collector} is specified by four functions that work together to
* accumulate entries into a mutable result container, and optionally perform
- * a final transform on the result. They are: creation of a new result container,
- * incorporating a new data element into a result container, combining two
- * result containers into one, and performing a final transform on the container.
- * The combiner function is used during parallel operations, where
- * subsets of the input are accumulated into separate result
- * containers, and then the subresults merged into a combined result. The
- * combiner function may merge one set of subresults into the other and return
- * that, or it may return a new object to describe the combined results.
+ * a final transform on the result. They are: <ul>
+ * <li>creation of a new result container ({@link #supplier()})</li>
+ * <li>incorporating a new data element into a result container ({@link #accumulator()})</li>
+ * <li>combining two result containers into one ({@link #combiner()})</li>
+ * <li>performing an optional final transform on the container ({@link #finisher()})</li>
+ * </ul>
*
* <p>Collectors also have a set of characteristics, such as
- * {@link Characteristics#CONCURRENT}. These characteristics provide
- * hints that can be used by a reduction implementation to provide better
- * performance.
+ * {@link Characteristics#CONCURRENT}, that provide hints that can be used by a
+ * reduction implementation to provide better performance.
+ *
+ * <p>A sequential implementation of a reduction using a collector would
+ * create a single result container using the supplier function, and invoke the
+ * accumulator function once for each input element. A parallel implementation
+ * would partition the input, create a result container for each partition,
+ * accumulate the contents of each partition into a subresult for that partition,
+ * and then use the combiner function to merge the subresults into a combined
+ * result.
+ *
+ * <p>To ensure that sequential and parallel executions produce equivalent
+ * results, the collector functions must satisfy an <em>identity</em> and an
+ * <a href="package-summary.html#Associativity">associativity</a> constraints.
+ *
+ * <p>The identity constraint says that for any partially accumulated result,
+ * combining it with an empty result container must produce an equivalent
+ * result. That is, for a partially accumulated result {@code a} that is the
+ * result of any series of accumulator and combiner invocations, {@code a} must
+ * be equivalent to {@code combiner.apply(a, supplier.get())}.
+ *
+ * <p>The associativity constraint says that splitting the computation must
+ * produce an equivalent result. That is, for any input elements {@code t1}
+ * and {@code t2}, the results {@code r1} and {@code r2} in the computation
+ * below must be equivalent:
+ * <pre>{@code
+ * A a1 = supplier.get();
+ * accumulator.accept(a1, t1);
+ * accumulator.accept(a1, t2);
+ * R r1 = finisher.apply(a1); // result without splitting
+ *
+ * A a2 = supplier.get();
+ * accumulator.accept(a2, t1);
+ * A a3 = supplier.get();
+ * accumulator.accept(a3, t2);
+ * R r2 = finisher.apply(combiner.apply(a2, a3)); // result with splitting
+ * } </pre>
+ *
+ * <p>For collectors that do not have the {@code UNORDERED} characteristic,
+ * two accumulated results {@code a1} and {@code a2} are equivalent if
+ * {@code finisher.apply(a1).equals(finisher.apply(a2))}. For unordered
+ * collectors, equivalence is relaxed to allow for non-equality related to
+ * differences in order. (For example, an unordered collector that accumulated
+ * elements to a {@code List} would consider two lists equivalent if they
+ * contained the same elements, ignoring order.)
*
* <p>Libraries that implement reduction based on {@code Collector}, such as
* {@link Stream#collect(Collector)}, must adhere to the following constraints:
@@ -132,6 +136,20 @@
* originating data is unordered.</li>
* </ul>
*
+ * <p>In addition to the predefined implementations in {@link Collectors}, the
+ * static factory methods {@link #of(Supplier, BiConsumer, BinaryOperator, Characteristics...)}
+ * can be used to construct collectors. For example, you could create a collector
+ * that accumulates widgets into a {@code TreeSet} with:
+ *
+ * <pre>{@code
+ * Collector<Widget, ?, TreeSet<Widget>> intoSet =
+ * Collector.of(TreeSet::new, TreeSet::add,
+ * (left, right) -> { left.addAll(right); return left; });
+ * }</pre>
+ *
+ * (This behavior is also implemented by the predefined collector
+ * {@link Collectors#toCollection(Supplier)}).
+ *
* @apiNote
* Performing a reduction operation with a {@code Collector} should produce a
* result equivalent to:
@@ -144,27 +162,35 @@
*
* <p>However, the library is free to partition the input, perform the reduction
* on the partitions, and then use the combiner function to combine the partial
- * results to achieve a parallel reduction. Depending on the specific reduction
+ * results to achieve a parallel reduction. (Depending on the specific reduction
* operation, this may perform better or worse, depending on the relative cost
- * of the accumulator and combiner functions.
+ * of the accumulator and combiner functions.)
+ *
+ * <p>Collectors are designed to be <em>composed</em>; many of the methods
+ * in {@link Collectors} are functions that take a collector and produce
+ * a new collector. For example, given the following collector that computes
+ * the sum of the salaries of a stream of employees:
*
- * <p>An example of an operation that can be easily modeled by {@code Collector}
- * is accumulating elements into a {@code TreeSet}. In this case, the {@code
- * resultSupplier()} function is {@code () -> new Treeset<T>()}, the
- * {@code accumulator} function is
- * {@code (set, element) -> set.add(element) }, and the combiner
- * function is {@code (left, right) -> { left.addAll(right); return left; }}.
- * (This behavior is implemented by
- * {@code Collectors.toCollection(TreeSet::new)}).
+ * <pre>{@code
+ * Collector<Employee, ?, Integer> summingSalaries
+ * = Collectors.summingInt(Employee::getSalary))
+ * }</pre>
*
- * TODO Associativity and commutativity
+ * If we wanted to create a collector to tabulate the sum of salaries by
+ * department, we could reuse the "sum of salaries" logic using
+ * {@link Collectors#groupingBy(Function, Collector)}:
+ *
+ * <pre>{@code
+ * Collector<Employee, ?, Map<Department, Integer>> summingSalariesByDept
+ * = Collectors.groupingBy(Employee::getDepartment, summingSalaries);
+ * }</pre>
*
* @see Stream#collect(Collector)
* @see Collectors
*
* @param <T> the type of input elements to the reduction operation
* @param <A> the mutable accumulation type of the reduction operation (often
- * hidden as an implementation detail)
+ * hidden as an implementation detail)
* @param <R> the result type of the reduction operation
* @since 1.8
*/
@@ -177,25 +203,25 @@
Supplier<A> supplier();
/**
- * A function that folds a new value into a mutable result container.
+ * A function that folds a value into a mutable result container.
*
- * @return a function which folds a new value into a mutable result container
+ * @return a function which folds a value into a mutable result container
*/
BiConsumer<A, T> accumulator();
/**
* A function that accepts two partial results and merges them. The
* combiner function may fold state from one argument into the other and
- * return that, or may return a new result object.
+ * return that, or may return a new result container.
*
- * @return a function which combines two partial results into a cumulative
+ * @return a function which combines two partial results into a combined
* result
*/
BinaryOperator<A> combiner();
/**
* Perform the final transformation from the intermediate accumulation type
- * {@code A} to the final result representation {@code R}.
+ * {@code A} to the final result type {@code R}.
*
* <p>If the characteristic {@code IDENTITY_TRANSFORM} is
* set, this function may be presumed to be an identity transform with an
@@ -228,12 +254,17 @@
* @param <T> The type of input elements for the new collector
* @param <R> The type of intermediate accumulation result, and final result,
* for the new collector
+ * @throws NullPointerException if any argument is null
* @return the new {@code Collector}
*/
public static<T, R> Collector<T, R, R> of(Supplier<R> supplier,
BiConsumer<R, T> accumulator,
BinaryOperator<R> combiner,
Characteristics... characteristics) {
+ Objects.requireNonNull(supplier);
+ Objects.requireNonNull(accumulator);
+ Objects.requireNonNull(combiner);
+ Objects.requireNonNull(characteristics);
Set<Characteristics> cs = (characteristics.length == 0)
? Collectors.CH_ID
: Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH,
@@ -254,6 +285,7 @@
* @param <T> The type of input elements for the new collector
* @param <A> The intermediate accumulation type of the new collector
* @param <R> The final result type of the new collector
+ * @throws NullPointerException if any argument is null
* @return the new {@code Collector}
*/
public static<T, A, R> Collector<T, A, R> of(Supplier<A> supplier,
@@ -261,6 +293,11 @@
BinaryOperator<A> combiner,
Function<A, R> finisher,
Characteristics... characteristics) {
+ Objects.requireNonNull(supplier);
+ Objects.requireNonNull(accumulator);
+ Objects.requireNonNull(combiner);
+ Objects.requireNonNull(finisher);
+ Objects.requireNonNull(characteristics);
Set<Characteristics> cs = Collectors.CH_NOID;
if (characteristics.length > 0) {
cs = EnumSet.noneOf(Characteristics.class);
@@ -288,8 +325,9 @@
CONCURRENT,
/**
- * Indicates that the result container has no intrinsic order, such as
- * a {@link Set}.
+ * Indicates that the collection operation does not commit to preserving
+ * the encounter order of input elements. (This might be true if the
+ * result container has no intrinsic order, such as a {@link Set}.)
*/
UNORDERED,
--- a/jdk/src/share/classes/java/util/stream/Collectors.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/Collectors.java Fri Sep 06 22:20:01 2013 -0700
@@ -62,37 +62,35 @@
* operations, such as accumulating elements into collections, summarizing
* elements according to various criteria, etc.
*
- * <p>The following are examples of using the predefined {@code Collector}
- * implementations in {@link Collectors} with the {@code Stream} API to perform
- * mutable reduction tasks:
+ * <p>The following are examples of using the predefined collectors to perform
+ * common mutable reduction tasks:
*
* <pre>{@code
* // Accumulate names into a List
* List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());
*
* // Accumulate names into a TreeSet
- * Set<String> list = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));
+ * Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));
*
* // Convert elements to strings and concatenate them, separated by commas
* String joined = things.stream()
* .map(Object::toString)
* .collect(Collectors.joining(", "));
*
- * // Find highest-paid employee
- * Employee highestPaid = employees.stream()
- * .collect(Collectors.maxBy(Comparator.comparing(Employee::getSalary)))
- * .get();
+ * // Compute sum of salaries of employee
+ * int total = employees.stream()
+ * .collect(Collectors.summingInt(Employee::getSalary)));
*
* // Group employees by department
* Map<Department, List<Employee>> byDept
* = employees.stream()
* .collect(Collectors.groupingBy(Employee::getDepartment));
*
- * // Find highest-paid employee by department
- * Map<Department, Optional<Employee>> highestPaidByDept
+ * // Compute sum of salaries by department
+ * Map<Department, Integer> totalByDept
* = employees.stream()
* .collect(Collectors.groupingBy(Employee::getDepartment,
- * Collectors.maxBy(Comparator.comparing(Employee::getSalary))));
+ * Collectors.summingInt(Employee::getSalary)));
*
* // Partition students into passing and failing
* Map<Boolean, List<Student>> passingFailing =
@@ -101,8 +99,6 @@
*
* }</pre>
*
- * TODO explanation of parallel collection
- *
* @since 1.8
*/
public final class Collectors {
@@ -222,7 +218,8 @@
/**
* Returns a {@code Collector} that accumulates the input elements into a
* new {@code List}. There are no guarantees on the type, mutability,
- * serializability, or thread-safety of the {@code List} returned.
+ * serializability, or thread-safety of the {@code List} returned; if more
+ * control over the returned {@code List} is required, use {@link #toCollection(Supplier)}.
*
* @param <T> the type of the input elements
* @return a {@code Collector} which collects all the input elements into a
@@ -238,7 +235,9 @@
/**
* Returns a {@code Collector} that accumulates the input elements into a
* new {@code Set}. There are no guarantees on the type, mutability,
- * serializability, or thread-safety of the {@code Set} returned.
+ * serializability, or thread-safety of the {@code Set} returned; if more
+ * control over the returned {@code Set} is required, use
+ * {@link #toCollection(Supplier)}.
*
* <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
* Collector.
@@ -903,7 +902,7 @@
* where the city names are sorted:
* <pre>{@code
* ConcurrentMap<City, Set<String>> namesByCity
- * = people.stream().collect(groupingByConcurrent(Person::getCity, ConcurrentSkipListMap::new,
+ * = people.stream().collect(groupingByConcurrent(Person::getCity,
* mapping(Person::getLastName, toSet())));
* }</pre>
*
--- a/jdk/src/share/classes/java/util/stream/DoublePipeline.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/DoublePipeline.java Fri Sep 06 22:20:01 2013 -0700
@@ -313,8 +313,8 @@
}
@Override
- public final DoubleStream peek(DoubleConsumer consumer) {
- Objects.requireNonNull(consumer);
+ public final DoubleStream peek(DoubleConsumer action) {
+ Objects.requireNonNull(action);
return new StatelessOp<Double>(this, StreamShape.DOUBLE_VALUE,
0) {
@Override
@@ -322,7 +322,7 @@
return new Sink.ChainedDouble<Double>(sink) {
@Override
public void accept(double t) {
- consumer.accept(t);
+ action.accept(t);
downstream.accept(t);
}
};
@@ -436,14 +436,14 @@
}
@Override
- public final <R> R collect(Supplier<R> resultFactory,
+ public final <R> R collect(Supplier<R> supplier,
ObjDoubleConsumer<R> accumulator,
BiConsumer<R, R> combiner) {
BinaryOperator<R> operator = (left, right) -> {
combiner.accept(left, right);
return left;
};
- return evaluate(ReduceOps.makeDouble(resultFactory, accumulator, operator));
+ return evaluate(ReduceOps.makeDouble(supplier, accumulator, operator));
}
@Override
--- a/jdk/src/share/classes/java/util/stream/DoubleStream.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/DoubleStream.java Fri Sep 06 22:20:01 2013 -0700
@@ -24,13 +24,18 @@
*/
package java.util.stream;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
+import java.util.Collection;
import java.util.DoubleSummaryStatistics;
import java.util.Objects;
import java.util.OptionalDouble;
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.Spliterators;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleConsumer;
@@ -45,40 +50,87 @@
import java.util.function.Supplier;
/**
- * A sequence of primitive double elements supporting sequential and parallel
- * bulk operations. Streams support lazy intermediate operations (transforming
- * a stream to another stream) such as {@code filter} and {@code map}, and terminal
- * operations (consuming the contents of a stream to produce a result or
- * side-effect), such as {@code forEach}, {@code findFirst}, and {@code
- * iterator}. Once an operation has been performed on a stream, it
- * is considered <em>consumed</em> and no longer usable for other operations.
+ * A sequence of elements supporting sequential and parallel aggregate
+ * operations. The following example illustrates an aggregate operation using
+ * {@link Stream} and {@link DoubleStream}:
+ *
+ * <pre>{@code
+ * double sum = widgets.stream()
+ * .filter(w -> w.getColor() == RED)
+ * .mapToDouble(w -> w.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 double} values representing the weight of
+ * each red widget. Then this stream is summed to produce a total weight.
*
- * <p>For sequential stream pipelines, all operations are performed in the
- * <a href="package-summary.html#Ordering">encounter order</a> of the pipeline
- * source, if the pipeline source has a defined encounter order.
+ * <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 DoubleStream#filter(DoublePredicate)}), and a
+ * <em>terminal operation</em> (which produces a result or side-effect, such
+ * as {@link DoubleStream#sum()} or {@link DoubleStream#forEach(DoubleConsumer)}.
+ * 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>For parallel stream pipelines, unless otherwise specified, intermediate
- * stream operations preserve the <a href="package-summary.html#Ordering">
- * encounter order</a> of their source, and terminal operations
- * respect the encounter order of their source, if the source
- * has an encounter order. Provided that and parameters to stream operations
- * satisfy the <a href="package-summary.html#NonInterference">non-interference
- * requirements</a>, and excepting differences arising from the absence of
- * a defined encounter order, the result of a stream pipeline should be the
- * stable across multiple executions of the same operations on the same source.
- * However, the timing and thread in which side-effects occur (for those
- * operations which are allowed to produce side-effects, such as
- * {@link #forEach(DoubleConsumer)}), are explicitly nondeterministic for parallel
- * execution of stream pipelines.
+ * <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 w -> w.getWeight()} passed to
+ * {@code mapToDouble} 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>Unless otherwise noted, passing a {@code null} argument to any stream
- * method may result in a {@link NullPointerException}.
+ * <p>A stream should be operated on (invoking 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.
*
- * @apiNote
- * Streams are not data structures; they do not manage the storage for their
- * elements, nor do they support access to individual elements. However,
- * you can use the {@link #iterator()} or {@link #spliterator()} operations to
- * perform a controlled traversal.
+ * <p>Streams have a {@link #close()} method and implement {@link AutoCloseable},
+ * but nearly all stream instances do not actually need to be closed after use.
+ * Generally, only streams whose source is an IO channel (such as those returned
+ * by {@link Files#lines(Path, Charset)}) will require closing. Most streams
+ * are backed by collections, arrays, or generating functions, which require no
+ * special resource management. (If a stream does require closing, it can be
+ * declared as a resource in a {@code try}-with-resources statement.)
+ *
+ * <p>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.) This choice of execution mode may be modified by the
+ * {@link #sequential()} or {@link #parallel()} methods, and may be queried with
+ * the {@link #isParallel()} method.
*
* @since 1.8
* @see <a href="package-summary.html">java.util.stream</a>
@@ -159,22 +211,13 @@
/**
* Returns a stream consisting of the results of replacing each element of
* this stream with the contents of the stream produced by applying the
- * provided mapping function to each element.
+ * provided mapping function to each element. (If the result of the mapping
+ * function is {@code null}, this is treated as if the result was an empty
+ * stream.)
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @apiNote
- * The {@code flatMap()} operation has the effect of applying a one-to-many
- * tranformation to the elements of the stream, and then flattening the
- * resulting elements into a new stream. For example, if {@code orders}
- * is a stream of purchase orders, and each purchase order contains a
- * collection of line items, then the following produces a stream of line
- * items:
- * <pre>{@code
- * orderStream.flatMap(order -> order.getLineItems().stream())...
- * }</pre>
- *
* @param mapper a <a href="package-summary.html#NonInterference">
* non-interfering, stateless</a> function to apply to
* each element which produces an {@code DoubleStream} of new
@@ -226,18 +269,18 @@
* <pre>{@code
* list.stream()
* .filter(filteringFunction)
- * .peek(e -> {System.out.println("Filtered value: " + e); });
+ * .peek(e -> System.out.println("Filtered value: " + e));
* .map(mappingFunction)
- * .peek(e -> {System.out.println("Mapped value: " + e); });
+ * .peek(e -> System.out.println("Mapped value: " + e));
* .collect(Collectors.toDoubleSummaryStastistics());
* }</pre>
*
- * @param consumer a <a href="package-summary.html#NonInterference">
+ * @param action a <a href="package-summary.html#NonInterference">
* non-interfering</a> action to perform on the elements as
* they are consumed from the stream
* @return the new stream
*/
- DoubleStream peek(DoubleConsumer consumer);
+ DoubleStream peek(DoubleConsumer action);
/**
* Returns a stream consisting of the elements of this stream, truncated
@@ -254,8 +297,8 @@
/**
* Returns a stream consisting of the remaining elements of this stream
- * after indexing {@code startInclusive} elements into the stream. If the
- * {@code startInclusive} index lies past the end of this stream then an
+ * after discarding the first {@code startInclusive} elements of the stream.
+ * If this stream contains fewer than {@code startInclusive} elements then an
* empty stream will be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">stateful
@@ -269,10 +312,10 @@
/**
* Returns a stream consisting of the remaining elements of this stream
- * after indexing {@code startInclusive} elements into the stream and
- * truncated to contain no more than {@code endExclusive - startInclusive}
- * elements. If the {@code startInclusive} index lies past the end
- * of this stream then an empty stream will be returned.
+ * after discarding the first {@code startInclusive} elements and truncating
+ * the result to be no longer than {@code endExclusive - startInclusive}
+ * elements in length. If this stream contains fewer than
+ * {@code startInclusive} elements then an empty stream will be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* stateful intermediate operation</a>.
@@ -421,12 +464,12 @@
/**
* Performs a <a href="package-summary.html#MutableReduction">mutable
* reduction</a> operation on the elements of this stream. A mutable
- * reduction is one in which the reduced value is a mutable value holder,
+ * reduction is one in which the reduced value is a mutable result container,
* such as an {@code ArrayList}, and elements are incorporated by updating
- * the state of the result, rather than by replacing the result. This
+ * the state of the result rather than by replacing the result. This
* produces a result equivalent to:
* <pre>{@code
- * R result = resultFactory.get();
+ * R result = supplier.get();
* for (double element : this stream)
* accumulator.accept(result, element);
* return result;
@@ -440,10 +483,9 @@
* operation</a>.
*
* @param <R> type of the result
- * @param resultFactory a 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 supplier a 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 an <a href="package-summary.html#Associativity">associative</a>
* <a href="package-summary.html#NonInterference">non-interfering,
* stateless</a> function for incorporating an additional
@@ -455,7 +497,7 @@
* @return the result of the reduction
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
- <R> R collect(Supplier<R> resultFactory,
+ <R> R collect(Supplier<R> supplier,
ObjDoubleConsumer<R> accumulator,
BiConsumer<R, R> combiner);
@@ -467,12 +509,15 @@
* yield more accurate results. If any stream element is a {@code NaN} or
* the sum is at any point a {@code NaN} then the sum will be {@code NaN}.
* This is a special case of a
- * <a href="package-summary.html#MutableReduction">reduction</a> and is
+ * <a href="package-summary.html#Reduction">reduction</a> and is
* equivalent to:
* <pre>{@code
* return reduce(0, Double::sum);
* }</pre>
*
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
+ *
* @return the sum of elements in this stream
*/
double sum();
@@ -483,12 +528,15 @@
* element will be {@code Double.NaN} if any stream element was NaN. Unlike
* the numerical comparison operators, this method considers negative zero
* to be strictly smaller than positive zero. This is a special case of a
- * <a href="package-summary.html#MutableReduction">reduction</a> and is
+ * <a href="package-summary.html#Reduction">reduction</a> and is
* equivalent to:
* <pre>{@code
* return reduce(Double::min);
* }</pre>
*
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
+ *
* @return an {@code OptionalDouble} containing the minimum element of this
* stream, or an empty optional if the stream is empty
*/
@@ -501,12 +549,15 @@
* the numerical comparison operators, this method considers negative zero
* to be strictly smaller than positive zero. This is a
* special case of a
- * <a href="package-summary.html#MutableReduction">reduction</a> and is
+ * <a href="package-summary.html#Reduction">reduction</a> and is
* equivalent to:
* <pre>{@code
* return reduce(Double::max);
* }</pre>
*
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
+ *
* @return an {@code OptionalDouble} containing the maximum element of this
* stream, or an empty optional if the stream is empty
*/
@@ -514,7 +565,7 @@
/**
* Returns the count of elements in this stream. This is a special case of
- * a <a href="package-summary.html#MutableReduction">reduction</a> and is
+ * a <a href="package-summary.html#Reduction">reduction</a> and is
* equivalent to:
* <pre>{@code
* return mapToLong(e -> 1L).sum();
@@ -535,7 +586,10 @@
* magnitude tend to yield more accurate results. If any recorded value is
* a {@code NaN} or the sum is at any point a {@code NaN} then the average
* will be {@code NaN}. This is a special case of a
- * <a href="package-summary.html#MutableReduction">reduction</a>.
+ * <a href="package-summary.html#Reduction">reduction</a>.
+ *
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
*
* @return an {@code OptionalDouble} containing the average element of this
* stream, or an empty optional if the stream is empty
@@ -545,7 +599,10 @@
/**
* Returns a {@code DoubleSummaryStatistics} describing various summary data
* about the elements of this stream. This is a special
- * case of a <a href="package-summary.html#MutableReduction">reduction</a>.
+ * case of a <a href="package-summary.html#Reduction">reduction</a>.
+ *
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
*
* @return a {@code DoubleSummaryStatistics} describing various summary data
* about the elements of this stream
@@ -602,9 +659,8 @@
/**
* Returns an {@link OptionalDouble} describing the first element of this
- * stream (in the encounter order), or an empty {@code OptionalDouble} if
- * the stream is empty. If the stream has no encounter order, then any
- * element may be returned.
+ * stream, or an empty {@code OptionalDouble} if the stream is empty. If
+ * the stream has no encounter order, then any element may be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
@@ -624,8 +680,8 @@
* <p>The behavior of this operation is explicitly nondeterministic; it is
* free to select any element in the stream. This is to allow for maximal
* performance in parallel operations; the cost is that multiple invocations
- * on the same source may not return the same result. (If the first element
- * in the encounter order is desired, use {@link #findFirst()} instead.)
+ * on the same source may not return the same result. (If a stable result
+ * is desired, use {@link #findFirst()} instead.)
*
* @return an {@code OptionalDouble} describing some element of this stream,
* or an empty {@code OptionalDouble} if the stream is empty
@@ -637,6 +693,9 @@
* Returns a {@code Stream} consisting of the elements of this stream,
* boxed to {@code Double}.
*
+ * <p>This is an <a href="package-summary.html#StreamOps">intermediate
+ * operation</a>.
+ *
* @return a {@code Stream} consistent of the elements of this stream,
* each boxed to a {@code Double}
*/
@@ -686,7 +745,7 @@
}
/**
- * Returns a sequential stream whose elements are the specified values.
+ * Returns a sequential ordered stream whose elements are the specified values.
*
* @param values the elements of the new stream
* @return the new stream
@@ -696,7 +755,7 @@
}
/**
- * Returns an infinite sequential {@code DoubleStream} produced by iterative
+ * Returns an infinite sequential ordered {@code DoubleStream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
@@ -734,8 +793,8 @@
}
/**
- * Returns a sequential {@code DoubleStream} where each element is
- * generated by an {@code DoubleSupplier}. This is suitable for generating
+ * Returns a sequential stream where each element is generated by
+ * the provided {@code DoubleSupplier}. This is suitable for generating
* constant streams, streams of random elements, etc.
*
* @param s the {@code DoubleSupplier} for generated elements
@@ -748,16 +807,16 @@
}
/**
- * Creates a lazy concatenated {@code DoubleStream} whose elements are all the
- * elements of a first {@code DoubleStream} succeeded by all the elements of the
- * second {@code DoubleStream}. The resulting stream is ordered if both
+ * Creates a lazily concatenated stream whose elements are all the
+ * elements of the first stream followed by all the elements of the
+ * second stream. The resulting stream is ordered if both
* of the input streams are ordered, and parallel if either of the input
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
* @param a the first stream
- * @param b the second stream to concatenate on to end of the first stream
- * @return the concatenation of the two streams
+ * @param b the second stream
+ * @return the concatenation of the two input streams
*/
public static DoubleStream concat(DoubleStream a, DoubleStream b) {
Objects.requireNonNull(a);
@@ -772,9 +831,9 @@
/**
* A mutable builder for a {@code DoubleStream}.
*
- * <p>A stream builder has a lifecycle, where it starts in a building
- * phase, during which elements can be added, and then transitions to a
- * built phase, after which elements may not be added. The built phase
+ * <p>A stream builder has a lifecycle, which starts in a building
+ * phase, during which elements can be added, and then transitions to a built
+ * phase, after which elements may not be added. The built phase
* begins when the {@link #build()} method is called, which creates an
* ordered stream whose elements are the elements that were added to the
* stream builder, in the order they were added.
--- a/jdk/src/share/classes/java/util/stream/IntPipeline.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/IntPipeline.java Fri Sep 06 22:20:01 2013 -0700
@@ -349,8 +349,8 @@
}
@Override
- public final IntStream peek(IntConsumer consumer) {
- Objects.requireNonNull(consumer);
+ public final IntStream peek(IntConsumer action) {
+ Objects.requireNonNull(action);
return new StatelessOp<Integer>(this, StreamShape.INT_VALUE,
0) {
@Override
@@ -358,7 +358,7 @@
return new Sink.ChainedInt<Integer>(sink) {
@Override
public void accept(int t) {
- consumer.accept(t);
+ action.accept(t);
downstream.accept(t);
}
};
@@ -473,14 +473,14 @@
}
@Override
- public final <R> R collect(Supplier<R> resultFactory,
+ public final <R> R collect(Supplier<R> supplier,
ObjIntConsumer<R> accumulator,
BiConsumer<R, R> combiner) {
BinaryOperator<R> operator = (left, right) -> {
combiner.accept(left, right);
return left;
};
- return evaluate(ReduceOps.makeInt(resultFactory, accumulator, operator));
+ return evaluate(ReduceOps.makeInt(supplier, accumulator, operator));
}
@Override
--- a/jdk/src/share/classes/java/util/stream/IntStream.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/IntStream.java Fri Sep 06 22:20:01 2013 -0700
@@ -24,7 +24,11 @@
*/
package java.util.stream;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
+import java.util.Collection;
import java.util.IntSummaryStatistics;
import java.util.Objects;
import java.util.OptionalDouble;
@@ -32,6 +36,7 @@
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.Spliterators;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.IntBinaryOperator;
@@ -46,40 +51,87 @@
import java.util.function.Supplier;
/**
- * A sequence of primitive integer elements supporting sequential and parallel
- * bulk operations. Streams support lazy intermediate operations (transforming
- * a stream to another stream) such as {@code filter} and {@code map}, and terminal
- * operations (consuming the contents of a stream to produce a result or
- * side-effect), such as {@code forEach}, {@code findFirst}, and {@code
- * iterator}. Once an operation has been performed on a stream, it
- * is considered <em>consumed</em> and no longer usable for other operations.
+ * A sequence of elements supporting sequential and parallel aggregate
+ * operations. The following example illustrates an aggregate operation using
+ * {@link Stream} and {@link IntStream}:
+ *
+ * <pre>{@code
+ * int sum = widgets.stream()
+ * .filter(w -> w.getColor() == RED)
+ * .mapToInt(w -> w.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>For sequential stream pipelines, all operations are performed in the
- * <a href="package-summary.html#Ordering">encounter order</a> of the pipeline
- * source, if the pipeline source has a defined encounter order.
+ * <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 IntStream#filter(IntPredicate)}), 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>For parallel stream pipelines, unless otherwise specified, intermediate
- * stream operations preserve the <a href="package-summary.html#Ordering">
- * encounter order</a> of their source, and terminal operations
- * respect the encounter order of their source, if the source
- * has an encounter order. Provided that and parameters to stream operations
- * satisfy the <a href="package-summary.html#NonInterference">non-interference
- * requirements</a>, and excepting differences arising from the absence of
- * a defined encounter order, the result of a stream pipeline should be the
- * stable across multiple executions of the same operations on the same source.
- * However, the timing and thread in which side-effects occur (for those
- * operations which are allowed to produce side-effects, such as
- * {@link #forEach(IntConsumer)}), are explicitly nondeterministic for parallel
- * execution of stream pipelines.
+ * <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 w -> w.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>Unless otherwise noted, passing a {@code null} argument to any stream
- * method may result in a {@link NullPointerException}.
+ * <p>A stream should be operated on (invoking 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.
*
- * @apiNote
- * Streams are not data structures; they do not manage the storage for their
- * elements, nor do they support access to individual elements. However,
- * you can use the {@link #iterator()} or {@link #spliterator()} operations to
- * perform a controlled traversal.
+ * <p>Streams have a {@link #close()} method and implement {@link AutoCloseable},
+ * but nearly all stream instances do not actually need to be closed after use.
+ * Generally, only streams whose source is an IO channel (such as those returned
+ * by {@link Files#lines(Path, Charset)}) will require closing. Most streams
+ * are backed by collections, arrays, or generating functions, which require no
+ * special resource management. (If a stream does require closing, it can be
+ * declared as a resource in a {@code try}-with-resources statement.)
+ *
+ * <p>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.) This choice of execution mode may be modified by the
+ * {@link #sequential()} or {@link #parallel()} methods, and may be queried with
+ * the {@link #isParallel()} method.
*
* @since 1.8
* @see <a href="package-summary.html">java.util.stream</a>
@@ -160,22 +212,13 @@
/**
* Returns a stream consisting of the results of replacing each element of
* this stream with the contents of the stream produced by applying the
- * provided mapping function to each element.
+ * provided mapping function to each element. (If the result of the mapping
+ * function is {@code null}, this is treated as if the result was an empty
+ * stream.)
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @apiNote
- * The {@code flatMap()} operation has the effect of applying a one-to-many
- * tranformation to the elements of the stream, and then flattening the
- * resulting elements into a new stream. For example, if {@code orders}
- * is a stream of purchase orders, and each purchase order contains a
- * collection of line items, then the following produces a stream of line
- * items:
- * <pre>{@code
- * orderStream.flatMap(order -> order.getLineItems().stream())...
- * }</pre>
- *
* @param mapper a <a href="package-summary.html#NonInterference">
* non-interfering, stateless</a> function to apply to
* each element which produces an {@code IntStream} of new
@@ -224,18 +267,18 @@
* <pre>{@code
* list.stream()
* .filter(filteringFunction)
- * .peek(e -> {System.out.println("Filtered value: " + e); });
+ * .peek(e -> System.out.println("Filtered value: " + e));
* .map(mappingFunction)
- * .peek(e -> {System.out.println("Mapped value: " + e); });
+ * .peek(e -> System.out.println("Mapped value: " + e));
* .collect(Collectors.toIntSummaryStastistics());
* }</pre>
*
- * @param consumer a <a href="package-summary.html#NonInterference">
- * non-interfering</a> action to perform on the elements as
- * they are consumed from the stream
+ * @param action a <a href="package-summary.html#NonInterference">
+ * non-interfering</a> action to perform on the elements as
+ * they are consumed from the stream
* @return the new stream
*/
- IntStream peek(IntConsumer consumer);
+ IntStream peek(IntConsumer action);
/**
* Returns a stream consisting of the elements of this stream, truncated
@@ -252,8 +295,8 @@
/**
* Returns a stream consisting of the remaining elements of this stream
- * after indexing {@code startInclusive} elements into the stream. If the
- * {@code startInclusive} index lies past the end of this stream then an
+ * after discarding the first {@code startInclusive} elements of the stream.
+ * If this stream contains fewer than {@code startInclusive} elements then an
* empty stream will be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">stateful
@@ -267,10 +310,10 @@
/**
* Returns a stream consisting of the remaining elements of this stream
- * after indexing {@code startInclusive} elements into the stream and
- * truncated to contain no more than {@code endExclusive - startInclusive}
- * elements. If the {@code startInclusive} index lies past the end
- * of this stream then an empty stream will be returned.
+ * after discarding the first {@code startInclusive} elements and truncating
+ * the result to be no longer than {@code endExclusive - startInclusive}
+ * elements in length. If this stream contains fewer than
+ * {@code startInclusive} elements then an empty stream will be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* stateful intermediate operation</a>.
@@ -419,12 +462,12 @@
/**
* Performs a <a href="package-summary.html#MutableReduction">mutable
* reduction</a> operation on the elements of this stream. A mutable
- * reduction is one in which the reduced value is a mutable value holder,
+ * reduction is one in which the reduced value is a mutable result container,
* such as an {@code ArrayList}, and elements are incorporated by updating
- * the state of the result, rather than by replacing the result. This
+ * the state of the result rather than by replacing the result. This
* produces a result equivalent to:
* <pre>{@code
- * R result = resultFactory.get();
+ * R result = supplier.get();
* for (int element : this stream)
* accumulator.accept(result, element);
* return result;
@@ -437,10 +480,9 @@
* operation</a>.
*
* @param <R> type of the result
- * @param resultFactory a 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 supplier a 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 an <a href="package-summary.html#Associativity">associative</a>
* <a href="package-summary.html#NonInterference">non-interfering,
* stateless</a> function for incorporating an additional
@@ -452,18 +494,21 @@
* @return the result of the reduction
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
- <R> R collect(Supplier<R> resultFactory,
+ <R> R collect(Supplier<R> supplier,
ObjIntConsumer<R> accumulator,
BiConsumer<R, R> combiner);
/**
* Returns the sum of elements in this stream. This is a special case
- * of a <a href="package-summary.html#MutableReduction">reduction</a>
+ * of a <a href="package-summary.html#Reduction">reduction</a>
* and is equivalent to:
* <pre>{@code
* return reduce(0, Integer::sum);
* }</pre>
*
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
+ *
* @return the sum of elements in this stream
*/
int sum();
@@ -471,7 +516,7 @@
/**
* Returns an {@code OptionalInt} describing the minimum element of this
* stream, or an empty optional if this stream is empty. This is a special
- * case of a <a href="package-summary.html#MutableReduction">reduction</a>
+ * case of a <a href="package-summary.html#Reduction">reduction</a>
* and is equivalent to:
* <pre>{@code
* return reduce(Integer::min);
@@ -479,7 +524,6 @@
*
* <p>This is a <a href="package-summary.html#StreamOps">terminal operation</a>.
*
-
* @return an {@code OptionalInt} containing the minimum element of this
* stream, or an empty {@code OptionalInt} if the stream is empty
*/
@@ -488,7 +532,7 @@
/**
* Returns an {@code OptionalInt} describing the maximum element of this
* stream, or an empty optional if this stream is empty. This is a special
- * case of a <a href="package-summary.html#MutableReduction">reduction</a>
+ * case of a <a href="package-summary.html#Reduction">reduction</a>
* and is equivalent to:
* <pre>{@code
* return reduce(Integer::max);
@@ -504,7 +548,7 @@
/**
* Returns the count of elements in this stream. This is a special case of
- * a <a href="package-summary.html#MutableReduction">reduction</a> and is
+ * a <a href="package-summary.html#Reduction">reduction</a> and is
* equivalent to:
* <pre>{@code
* return mapToLong(e -> 1L).sum();
@@ -520,7 +564,10 @@
* Returns an {@code OptionalDouble} describing the arithmetic mean of elements of
* this stream, or an empty optional if this stream is empty. This is a
* special case of a
- * <a href="package-summary.html#MutableReduction">reduction</a>.
+ * <a href="package-summary.html#Reduction">reduction</a>.
+ *
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
*
* @return an {@code OptionalDouble} containing the average element of this
* stream, or an empty optional if the stream is empty
@@ -530,7 +577,10 @@
/**
* Returns an {@code IntSummaryStatistics} describing various
* summary data about the elements of this stream. This is a special
- * case of a <a href="package-summary.html#MutableReduction">reduction</a>.
+ * case of a <a href="package-summary.html#Reduction">reduction</a>.
+ *
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
*
* @return an {@code IntSummaryStatistics} describing various summary data
* about the elements of this stream
@@ -587,9 +637,8 @@
/**
* Returns an {@link OptionalInt} describing the first element of this
- * stream (in the encounter order), or an empty {@code OptionalInt} if the
- * stream is empty. If the stream has no encounter order, then any element
- * may be returned.
+ * stream, or an empty {@code OptionalInt} if the stream is empty. If the
+ * stream has no encounter order, then any element may be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
@@ -609,8 +658,8 @@
* <p>The behavior of this operation is explicitly nondeterministic; it is
* free to select any element in the stream. This is to allow for maximal
* performance in parallel operations; the cost is that multiple invocations
- * on the same source may not return the same result. (If the first element
- * in the encounter order is desired, use {@link #findFirst()} instead.)
+ * on the same source may not return the same result. (If a stable result
+ * is desired, use {@link #findFirst()} instead.)
*
* @return an {@code OptionalInt} describing some element of this stream, or
* an empty {@code OptionalInt} if the stream is empty
@@ -622,6 +671,9 @@
* Returns a {@code LongStream} consisting of the elements of this stream,
* converted to {@code long}.
*
+ * <p>This is an <a href="package-summary.html#StreamOps">intermediate
+ * operation</a>.
+ *
* @return a {@code LongStream} consisting of the elements of this stream,
* converted to {@code long}
*/
@@ -631,6 +683,9 @@
* Returns a {@code DoubleStream} consisting of the elements of this stream,
* converted to {@code double}.
*
+ * <p>This is an <a href="package-summary.html#StreamOps">intermediate
+ * operation</a>.
+ *
* @return a {@code DoubleStream} consisting of the elements of this stream,
* converted to {@code double}
*/
@@ -640,6 +695,9 @@
* Returns a {@code Stream} consisting of the elements of this stream,
* each boxed to an {@code Integer}.
*
+ * <p>This is an <a href="package-summary.html#StreamOps">intermediate
+ * operation</a>.
+ *
* @return a {@code Stream} consistent of the elements of this stream,
* each boxed to an {@code Integer}
*/
@@ -688,7 +746,7 @@
}
/**
- * Returns a sequential stream whose elements are the specified values.
+ * Returns a sequential ordered stream whose elements are the specified values.
*
* @param values the elements of the new stream
* @return the new stream
@@ -698,7 +756,7 @@
}
/**
- * Returns an infinite sequential {@code IntStream} produced by iterative
+ * Returns an infinite sequential ordered {@code IntStream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
@@ -736,8 +794,8 @@
}
/**
- * Returns a sequential {@code IntStream} where each element is
- * generated by an {@code IntSupplier}. This is suitable for generating
+ * Returns a sequential stream where each element is generated by
+ * the provided {@code IntSupplier}. This is suitable for generating
* constant streams, streams of random elements, etc.
*
* @param s the {@code IntSupplier} for generated elements
@@ -750,7 +808,7 @@
}
/**
- * Returns a sequential {@code IntStream} from {@code startInclusive}
+ * Returns a sequential ordered {@code IntStream} from {@code startInclusive}
* (inclusive) to {@code endExclusive} (exclusive) by an incremental step of
* {@code 1}.
*
@@ -776,7 +834,7 @@
}
/**
- * Returns a sequential {@code IntStream} from {@code startInclusive}
+ * Returns a sequential ordered {@code IntStream} from {@code startInclusive}
* (inclusive) to {@code endInclusive} (inclusive) by an incremental step of
* {@code 1}.
*
@@ -802,16 +860,16 @@
}
/**
- * Creates a lazy concatenated {@code IntStream} whose elements are all the
- * elements of a first {@code IntStream} succeeded by all the elements of the
- * second {@code IntStream}. The resulting stream is ordered if both
+ * Creates a lazily concatenated stream whose elements are all the
+ * elements of the first stream followed by all the elements of the
+ * second stream. The resulting stream is ordered if both
* of the input streams are ordered, and parallel if either of the input
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
* @param a the first stream
- * @param b the second stream to concatenate on to end of the first stream
- * @return the concatenation of the two streams
+ * @param b the second stream
+ * @return the concatenation of the two input streams
*/
public static IntStream concat(IntStream a, IntStream b) {
Objects.requireNonNull(a);
@@ -826,9 +884,9 @@
/**
* A mutable builder for an {@code IntStream}.
*
- * <p>A stream builder has a lifecycle, where it starts in a building
- * phase, during which elements can be added, and then transitions to a
- * built phase, after which elements may not be added. The built phase
+ * <p>A stream builder has a lifecycle, which starts in a building
+ * phase, during which elements can be added, and then transitions to a built
+ * phase, after which elements may not be added. The built phase
* begins when the {@link #build()} method is called, which creates an
* ordered stream whose elements are the elements that were added to the
* stream builder, in the order they were added.
--- a/jdk/src/share/classes/java/util/stream/LongPipeline.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/LongPipeline.java Fri Sep 06 22:20:01 2013 -0700
@@ -330,8 +330,8 @@
}
@Override
- public final LongStream peek(LongConsumer consumer) {
- Objects.requireNonNull(consumer);
+ public final LongStream peek(LongConsumer action) {
+ Objects.requireNonNull(action);
return new StatelessOp<Long>(this, StreamShape.LONG_VALUE,
0) {
@Override
@@ -339,7 +339,7 @@
return new Sink.ChainedLong<Long>(sink) {
@Override
public void accept(long t) {
- consumer.accept(t);
+ action.accept(t);
downstream.accept(t);
}
};
@@ -455,14 +455,14 @@
}
@Override
- public final <R> R collect(Supplier<R> resultFactory,
+ public final <R> R collect(Supplier<R> supplier,
ObjLongConsumer<R> accumulator,
BiConsumer<R, R> combiner) {
BinaryOperator<R> operator = (left, right) -> {
combiner.accept(left, right);
return left;
};
- return evaluate(ReduceOps.makeLong(resultFactory, accumulator, operator));
+ return evaluate(ReduceOps.makeLong(supplier, accumulator, operator));
}
@Override
--- a/jdk/src/share/classes/java/util/stream/LongStream.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/LongStream.java Fri Sep 06 22:20:01 2013 -0700
@@ -24,7 +24,11 @@
*/
package java.util.stream;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
+import java.util.Collection;
import java.util.LongSummaryStatistics;
import java.util.Objects;
import java.util.OptionalDouble;
@@ -32,6 +36,7 @@
import java.util.PrimitiveIterator;
import java.util.Spliterator;
import java.util.Spliterators;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.LongBinaryOperator;
@@ -46,40 +51,87 @@
import java.util.function.Supplier;
/**
- * A sequence of primitive long elements supporting sequential and parallel
- * bulk operations. Streams support lazy intermediate operations (transforming
- * a stream to another stream) such as {@code filter} and {@code map}, and terminal
- * operations (consuming the contents of a stream to produce a result or
- * side-effect), such as {@code forEach}, {@code findFirst}, and {@code
- * iterator}. Once an operation has been performed on a stream, it
- * is considered <em>consumed</em> and no longer usable for other operations.
+ * A sequence of elements supporting sequential and parallel aggregate
+ * operations. The following example illustrates an aggregate operation using
+ * {@link Stream} and {@link LongStream}:
+ *
+ * <pre>{@code
+ * long sum = widgets.stream()
+ * .filter(w -> w.getColor() == RED)
+ * .mapToLong(w -> w.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 long} values representing the weight of
+ * each red widget. Then this stream is summed to produce a total weight.
*
- * <p>For sequential stream pipelines, all operations are performed in the
- * <a href="package-summary.html#Ordering">encounter order</a> of the pipeline
- * source, if the pipeline source has a defined encounter order.
+ * <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 LongStream#filter(LongPredicate)}), and a
+ * <em>terminal operation</em> (which produces a result or side-effect, such
+ * as {@link LongStream#sum()} or {@link LongStream#forEach(LongConsumer)}).
+ * 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>For parallel stream pipelines, unless otherwise specified, intermediate
- * stream operations preserve the <a href="package-summary.html#Ordering">
- * encounter order</a> of their source, and terminal operations
- * respect the encounter order of their source, if the source
- * has an encounter order. Provided that and parameters to stream operations
- * satisfy the <a href="package-summary.html#NonInterference">non-interference
- * requirements</a>, and excepting differences arising from the absence of
- * a defined encounter order, the result of a stream pipeline should be the
- * stable across multiple executions of the same operations on the same source.
- * However, the timing and thread in which side-effects occur (for those
- * operations which are allowed to produce side-effects, such as
- * {@link #forEach(LongConsumer)}), are explicitly nondeterministic for parallel
- * execution of stream pipelines.
+ * <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 w -> w.getWeight()} passed to
+ * {@code mapToLong} 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>Unless otherwise noted, passing a {@code null} argument to any stream
- * method may result in a {@link NullPointerException}.
+ * <p>A stream should be operated on (invoking 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.
*
- * @apiNote
- * Streams are not data structures; they do not manage the storage for their
- * elements, nor do they support access to individual elements. However,
- * you can use the {@link #iterator()} or {@link #spliterator()} operations to
- * perform a controlled traversal.
+ * <p>Streams have a {@link #close()} method and implement {@link AutoCloseable},
+ * but nearly all stream instances do not actually need to be closed after use.
+ * Generally, only streams whose source is an IO channel (such as those returned
+ * by {@link Files#lines(Path, Charset)}) will require closing. Most streams
+ * are backed by collections, arrays, or generating functions, which require no
+ * special resource management. (If a stream does require closing, it can be
+ * declared as a resource in a {@code try}-with-resources statement.)
+ *
+ * <p>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.) This choice of execution mode may be modified by the
+ * {@link #sequential()} or {@link #parallel()} methods, and may be queried with
+ * the {@link #isParallel()} method.
*
* @since 1.8
* @see <a href="package-summary.html">java.util.stream</a>
@@ -160,22 +212,13 @@
/**
* Returns a stream consisting of the results of replacing each element of
* this stream with the contents of the stream produced by applying the
- * provided mapping function to each element.
+ * provided mapping function to each element. (If the result of the mapping
+ * function is {@code null}, this is treated as if the result was an empty
+ * stream.)
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
*
- * @apiNote
- * The {@code flatMap()} operation has the effect of applying a one-to-many
- * tranformation to the elements of the stream, and then flattening the
- * resulting elements into a new stream. For example, if {@code orders}
- * is a stream of purchase orders, and each purchase order contains a
- * collection of line items, then the following produces a stream of line
- * items:
- * <pre>{@code
- * orderStream.flatMap(order -> order.getLineItems().stream())...
- * }</pre>
- *
* @param mapper a <a href="package-summary.html#NonInterference">
* non-interfering, stateless</a> function to apply to
* each element which produces an {@code LongStream} of new
@@ -224,18 +267,18 @@
* <pre>{@code
* list.stream()
* .filter(filteringFunction)
- * .peek(e -> {System.out.println("Filtered value: " + e); });
+ * .peek(e -> System.out.println("Filtered value: " + e));
* .map(mappingFunction)
- * .peek(e -> {System.out.println("Mapped value: " + e); });
+ * .peek(e -> System.out.println("Mapped value: " + e));
* .collect(Collectors.toLongSummaryStastistics());
* }</pre>
*
- * @param consumer a <a href="package-summary.html#NonInterference">
- * non-interfering</a> action to perform on the elements as
- * they are consumed from the stream
+ * @param action a <a href="package-summary.html#NonInterference">
+ * non-interfering</a> action to perform on the elements as
+ * they are consumed from the stream
* @return the new stream
*/
- LongStream peek(LongConsumer consumer);
+ LongStream peek(LongConsumer action);
/**
* Returns a stream consisting of the elements of this stream, truncated
@@ -252,8 +295,8 @@
/**
* Returns a stream consisting of the remaining elements of this stream
- * after indexing {@code startInclusive} elements into the stream. If the
- * {@code startInclusive} index lies past the end of this stream then an
+ * after discarding the first {@code startInclusive} elements of the stream.
+ * If this stream contains fewer than {@code startInclusive} elements then an
* empty stream will be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">stateful
@@ -267,10 +310,10 @@
/**
* Returns a stream consisting of the remaining elements of this stream
- * after indexing {@code startInclusive} elements into the stream and
- * truncated to contain no more than {@code endExclusive - startInclusive}
- * elements. If the {@code startInclusive} index lies past the end
- * of this stream then an empty stream will be returned.
+ * after discarding the first {@code startInclusive} elements and truncating
+ * the result to be no longer than {@code endExclusive - startInclusive}
+ * elements in length. If this stream contains fewer than
+ * {@code startInclusive} elements then an empty stream will be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* stateful intermediate operation</a>.
@@ -419,12 +462,12 @@
/**
* Performs a <a href="package-summary.html#MutableReduction">mutable
* reduction</a> operation on the elements of this stream. A mutable
- * reduction is one in which the reduced value is a mutable value holder,
+ * reduction is one in which the reduced value is a mutable result container,
* such as an {@code ArrayList}, and elements are incorporated by updating
- * the state of the result, rather than by replacing the result. This
+ * the state of the result rather than by replacing the result. This
* produces a result equivalent to:
* <pre>{@code
- * R result = resultFactory.get();
+ * R result = supplier.get();
* for (long element : this stream)
* accumulator.accept(result, element);
* return result;
@@ -437,10 +480,9 @@
* operation</a>.
*
* @param <R> type of the result
- * @param resultFactory a 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 supplier a 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 an <a href="package-summary.html#Associativity">associative</a>
* <a href="package-summary.html#NonInterference">non-interfering,
* stateless</a> function for incorporating an additional
@@ -452,18 +494,21 @@
* @return the result of the reduction
* @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/
- <R> R collect(Supplier<R> resultFactory,
+ <R> R collect(Supplier<R> supplier,
ObjLongConsumer<R> accumulator,
BiConsumer<R, R> combiner);
/**
* Returns the sum of elements in this stream. This is a special case
- * of a <a href="package-summary.html#MutableReduction">reduction</a>
+ * of a <a href="package-summary.html#Reduction">reduction</a>
* and is equivalent to:
* <pre>{@code
* return reduce(0, Long::sum);
* }</pre>
*
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
+ *
* @return the sum of elements in this stream
*/
long sum();
@@ -471,7 +516,7 @@
/**
* Returns an {@code OptionalLong} describing the minimum element of this
* stream, or an empty optional if this stream is empty. This is a special
- * case of a <a href="package-summary.html#MutableReduction">reduction</a>
+ * case of a <a href="package-summary.html#Reduction">reduction</a>
* and is equivalent to:
* <pre>{@code
* return reduce(Long::min);
@@ -479,7 +524,6 @@
*
* <p>This is a <a href="package-summary.html#StreamOps">terminal operation</a>.
*
-
* @return an {@code OptionalLong} containing the minimum element of this
* stream, or an empty {@code OptionalLong} if the stream is empty
*/
@@ -488,7 +532,7 @@
/**
* Returns an {@code OptionalLong} describing the maximum element of this
* stream, or an empty optional if this stream is empty. This is a special
- * case of a <a href="package-summary.html#MutableReduction">reduction</a>
+ * case of a <a href="package-summary.html#Reduction">reduction</a>
* and is equivalent to:
* <pre>{@code
* return reduce(Long::max);
@@ -504,7 +548,7 @@
/**
* Returns the count of elements in this stream. This is a special case of
- * a <a href="package-summary.html#MutableReduction">reduction</a> and is
+ * a <a href="package-summary.html#Reduction">reduction</a> and is
* equivalent to:
* <pre>{@code
* return map(e -> 1L).sum();
@@ -520,7 +564,10 @@
* Returns an {@code OptionalDouble} describing the arithmetic mean of elements of
* this stream, or an empty optional if this stream is empty. This is a
* special case of a
- * <a href="package-summary.html#MutableReduction">reduction</a>.
+ * <a href="package-summary.html#Reduction">reduction</a>.
+ *
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
*
* @return an {@code OptionalDouble} containing the average element of this
* stream, or an empty optional if the stream is empty
@@ -530,7 +577,10 @@
/**
* Returns a {@code LongSummaryStatistics} describing various summary data
* about the elements of this stream. This is a special case of a
- * <a href="package-summary.html#MutableReduction">reduction</a>.
+ * <a href="package-summary.html#Reduction">reduction</a>.
+ *
+ * <p>This is a <a href="package-summary.html#StreamOps">terminal
+ * operation</a>.
*
* @return a {@code LongSummaryStatistics} describing various summary data
* about the elements of this stream
@@ -587,9 +637,8 @@
/**
* Returns an {@link OptionalLong} describing the first element of this
- * stream (in the encounter order), or an empty {@code OptionalLong} if the
- * stream is empty. If the stream has no encounter order, then any element
- * may be returned.
+ * stream, or an empty {@code OptionalLong} if the stream is empty. If the
+ * stream has no encounter order, then any element may be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
@@ -609,8 +658,8 @@
* <p>The behavior of this operation is explicitly nondeterministic; it is
* free to select any element in the stream. This is to allow for maximal
* performance in parallel operations; the cost is that multiple invocations
- * on the same source may not return the same result. (If the first element
- * in the encounter order is desired, use {@link #findFirst()} instead.)
+ * on the same source may not return the same result. (If a stable result
+ * is desired, use {@link #findFirst()} instead.)
*
* @return an {@code OptionalLong} describing some element of this stream,
* or an empty {@code OptionalLong} if the stream is empty
@@ -622,6 +671,9 @@
* Returns a {@code DoubleStream} consisting of the elements of this stream,
* converted to {@code double}.
*
+ * <p>This is an <a href="package-summary.html#StreamOps">intermediate
+ * operation</a>.
+ *
* @return a {@code DoubleStream} consisting of the elements of this stream,
* converted to {@code double}
*/
@@ -631,6 +683,9 @@
* Returns a {@code Stream} consisting of the elements of this stream,
* each boxed to a {@code Long}.
*
+ * <p>This is an <a href="package-summary.html#StreamOps">intermediate
+ * operation</a>.
+ *
* @return a {@code Stream} consistent of the elements of this stream,
* each boxed to {@code Long}
*/
@@ -679,7 +734,7 @@
}
/**
- * Returns a sequential stream whose elements are the specified values.
+ * Returns a sequential ordered stream whose elements are the specified values.
*
* @param values the elements of the new stream
* @return the new stream
@@ -689,7 +744,7 @@
}
/**
- * Returns an infinite sequential {@code LongStream} produced by iterative
+ * Returns an infinite sequential ordered {@code LongStream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
@@ -727,9 +782,9 @@
}
/**
- * Returns a sequential {@code LongStream} where each element is generated
- * by a {@code LongSupplier}. This is suitable for generating constant
- * streams, streams of random elements, etc.
+ * Returns a sequential stream where each element is generated by
+ * the provided {@code LongSupplier}. This is suitable for generating
+ * constant streams, streams of random elements, etc.
*
* @param s the {@code LongSupplier} for generated elements
* @return a new sequential {@code LongStream}
@@ -741,7 +796,7 @@
}
/**
- * Returns a sequential {@code LongStream} from {@code startInclusive}
+ * Returns a sequential ordered {@code LongStream} from {@code startInclusive}
* (inclusive) to {@code endExclusive} (exclusive) by an incremental step of
* {@code 1}.
*
@@ -774,7 +829,7 @@
}
/**
- * Returns a sequential {@code LongStream} from {@code startInclusive}
+ * Returns a sequential ordered {@code LongStream} from {@code startInclusive}
* (inclusive) to {@code endInclusive} (inclusive) by an incremental step of
* {@code 1}.
*
@@ -808,16 +863,16 @@
}
/**
- * Creates a lazy concatenated {@code LongStream} whose elements are all the
- * elements of a first {@code LongStream} succeeded by all the elements of the
- * second {@code LongStream}. The resulting stream is ordered if both
+ * Creates a lazily concatenated stream whose elements are all the
+ * elements of the first stream followed by all the elements of the
+ * second stream. The resulting stream is ordered if both
* of the input streams are ordered, and parallel if either of the input
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
* @param a the first stream
- * @param b the second stream to concatenate on to end of the first stream
- * @return the concatenation of the two streams
+ * @param b the second stream
+ * @return the concatenation of the two input streams
*/
public static LongStream concat(LongStream a, LongStream b) {
Objects.requireNonNull(a);
@@ -832,9 +887,9 @@
/**
* A mutable builder for a {@code LongStream}.
*
- * <p>A stream builder has a lifecycle, where it starts in a building
- * phase, during which elements can be added, and then transitions to a
- * built phase, after which elements may not be added. The built phase
+ * <p>A stream builder has a lifecycle, which starts in a building
+ * phase, during which elements can be added, and then transitions to a built
+ * phase, after which elements may not be added. The built phase begins
* begins when the {@link #build()} method is called, which creates an
* ordered stream whose elements are the elements that were added to the
* stream builder, in the order they were added.
--- a/jdk/src/share/classes/java/util/stream/PipelineHelper.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/PipelineHelper.java Fri Sep 06 22:20:01 2013 -0700
@@ -28,7 +28,7 @@
import java.util.function.IntFunction;
/**
- * Helper class for executing <a href="package-summary.html#StreamPipelines">
+ * Helper class for executing <a href="package-summary.html#StreamOps">
* stream pipelines</a>, capturing all of the information about a stream
* pipeline (output shape, intermediate operations, stream flags, parallelism,
* etc) in one place.
--- a/jdk/src/share/classes/java/util/stream/ReferencePipeline.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/ReferencePipeline.java Fri Sep 06 22:20:01 2013 -0700
@@ -170,6 +170,7 @@
}
@Override
+ @SuppressWarnings("unchecked")
public void accept(P_OUT u) {
if (predicate.test(u))
downstream.accept(u);
@@ -263,6 +264,7 @@
}
@Override
+ @SuppressWarnings("unchecked")
public void accept(P_OUT u) {
try (Stream<? extends R> result = mapper.apply(u)) {
// We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
@@ -360,16 +362,17 @@
}
@Override
- public final Stream<P_OUT> peek(Consumer<? super P_OUT> tee) {
- Objects.requireNonNull(tee);
+ public final Stream<P_OUT> peek(Consumer<? super P_OUT> action) {
+ Objects.requireNonNull(action);
return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
0) {
@Override
Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
@Override
+ @SuppressWarnings("unchecked")
public void accept(P_OUT u) {
- tee.accept(u);
+ action.accept(u);
downstream.accept(u);
}
};
@@ -515,10 +518,10 @@
}
@Override
- public final <R> R collect(Supplier<R> resultFactory,
+ public final <R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super P_OUT> accumulator,
BiConsumer<R, R> combiner) {
- return evaluate(ReduceOps.makeRef(resultFactory, accumulator, combiner));
+ return evaluate(ReduceOps.makeRef(supplier, accumulator, combiner));
}
@Override
--- a/jdk/src/share/classes/java/util/stream/Stream.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/Stream.java Fri Sep 06 22:20:01 2013 -0700
@@ -24,13 +24,18 @@
*/
package java.util.stream;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Objects;
import java.util.Optional;
import java.util.Spliterator;
import java.util.Spliterators;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
@@ -44,51 +49,90 @@
import java.util.function.ToLongFunction;
import java.util.function.UnaryOperator;
-// @@@ 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
-// - Whether each op preserves encounter order
-// @@@ Specification to-do list @@@
-
/**
- * A sequence of elements supporting sequential and parallel bulk operations.
- * Streams support lazy intermediate operations (transforming a stream to
- * another stream) such as {@code filter} and {@code map}, and terminal
- * operations (consuming the contents of a stream to produce a result or
- * side-effect), such as {@code forEach}, {@code findFirst}, and {@code
- * iterator}. Once an operation has been performed on a stream, it
- * is considered <em>consumed</em> and no longer usable for other operations.
+ * A sequence of elements supporting sequential and parallel aggregate
+ * operations. The following example illustrates an aggregate operation using
+ * {@link Stream} and {@link IntStream}:
+ *
+ * <pre>{@code
+ * int sum = widgets.stream()
+ * .filter(w -> w.getColor() == RED)
+ * .mapToInt(w -> w.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>For sequential stream pipelines, all operations are performed in the
- * <a href="package-summary.html#Ordering">encounter order</a> of the pipeline
- * source, if the pipeline source has a defined encounter order.
+ * <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 I/O 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 Stream#count()} or {@link Stream#forEach(Consumer)}).
+ * 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>For parallel stream pipelines, unless otherwise specified, intermediate
- * stream operations preserve the <a href="package-summary.html#Ordering">
- * encounter order</a> of their source, and terminal operations
- * respect the encounter order of their source, if the source
- * has an encounter order. Provided that and parameters to stream operations
- * satisfy the <a href="package-summary.html#NonInterference">non-interference
- * requirements</a>, and excepting differences arising from the absence of
- * a defined encounter order, the result of a stream pipeline should be the
- * stable across multiple executions of the same operations on the same source.
- * However, the timing and thread in which side-effects occur (for those
- * operations which are allowed to produce side-effects, such as
- * {@link #forEach(Consumer)}), are explicitly nondeterministic for parallel
- * execution of stream pipelines.
+ * <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 w -> w.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>Unless otherwise noted, passing a {@code null} argument to any stream
- * method may result in a {@link NullPointerException}.
+ * <p>A stream should be operated on (invoking 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.
*
- * @apiNote
- * Streams are not data structures; they do not manage the storage for their
- * elements, nor do they support access to individual elements. However,
- * you can use the {@link #iterator()} or {@link #spliterator()} operations to
- * perform a controlled traversal.
+ * <p>Streams have a {@link #close()} method and implement {@link AutoCloseable},
+ * but nearly all stream instances do not actually need to be closed after use.
+ * Generally, only streams whose source is an IO channel (such as those returned
+ * by {@link Files#lines(Path, Charset)}) will require closing. Most streams
+ * are backed by collections, arrays, or generating functions, which require no
+ * special resource management. (If a stream does require closing, it can be
+ * declared as a resource in a {@code try}-with-resources statement.)
*
- * @param <T> type of elements
+ * <p>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.) This choice of execution mode may be modified by the
+ * {@link #sequential()} or {@link #parallel()} methods, and may be queried with
+ * the {@link #isParallel()} method.
+ *
+ * @param <T> the type of the stream elements
* @since 1.8
* @see <a href="package-summary.html">java.util.stream</a>
*/
@@ -168,9 +212,9 @@
/**
* Returns a stream consisting of the results of replacing each element of
* this stream with the contents of the stream produced by applying the
- * provided mapping function to each element. If the result of the mapping
- * function is {@code null}, this is treated as if the result is an empty
- * stream.
+ * provided mapping function to each element. (If the result of the mapping
+ * function is {@code null}, this is treated as if the result was an empty
+ * stream.)
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
@@ -197,9 +241,9 @@
/**
* Returns an {@code IntStream} consisting of the results of replacing each
* element of this stream with the contents of the stream produced by
- * applying the provided mapping function to each element. If the result of
- * the mapping function is {@code null}, this is treated as if the result is
- * an empty stream.
+ * applying the provided mapping function to each element. (If the result
+ * of the mapping function is {@code null}, this is treated as if the result
+ * was an empty stream.)
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
@@ -214,9 +258,9 @@
/**
* Returns a {@code LongStream} consisting of the results of replacing each
* element of this stream with the contents of the stream produced
- * by applying the provided mapping function to each element. If the result
- * of the mapping function is {@code null}, this is treated as if the
- * result is an empty stream.
+ * by applying the provided mapping function to each element. (If the result
+ * of the mapping function is {@code null}, this is treated as if the result
+ * was an empty stream.)
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
@@ -231,9 +275,9 @@
/**
* Returns a {@code DoubleStream} consisting of the results of replacing each
* element of this stream with the contents of the stream produced
- * by applying the provided mapping function to each element. If the result
+ * by applying the provided mapping function to each element. (If the result
* of the mapping function is {@code null}, this is treated as if the result
- * is an empty stream.
+ * was an empty stream.)
*
* <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>.
@@ -260,7 +304,7 @@
* Returns a stream consisting of the elements of this stream, sorted
* according to natural order. If the elements of this stream are not
* {@code Comparable}, a {@code java.lang.ClassCastException} may be thrown
- * when the stream pipeline is executed.
+ * when the terminal operation is executed.
*
* <p>This is a <a href="package-summary.html#StreamOps">stateful
* intermediate operation</a>.
@@ -301,18 +345,18 @@
* <pre>{@code
* list.stream()
* .filter(filteringFunction)
- * .peek(e -> {System.out.println("Filtered value: " + e); });
+ * .peek(e -> System.out.println("Filtered value: " + e));
* .map(mappingFunction)
- * .peek(e -> {System.out.println("Mapped value: " + e); });
+ * .peek(e -> System.out.println("Mapped value: " + e));
* .collect(Collectors.intoList());
* }</pre>
*
- * @param consumer a <a href="package-summary.html#NonInterference">
+ * @param action a <a href="package-summary.html#NonInterference">
* non-interfering</a> action to perform on the elements as
* they are consumed from the stream
* @return the new stream
*/
- Stream<T> peek(Consumer<? super T> consumer);
+ Stream<T> peek(Consumer<? super T> action);
/**
* Returns a stream consisting of the elements of this stream, truncated
@@ -329,8 +373,8 @@
/**
* Returns a stream consisting of the remaining elements of this stream
- * after indexing {@code startInclusive} elements into the stream. If the
- * {@code startInclusive} index lies past the end of this stream then an
+ * after discarding the first {@code startInclusive} elements of the stream.
+ * If this stream contains fewer than {@code startInclusive} elements then an
* empty stream will be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">stateful
@@ -344,10 +388,10 @@
/**
* Returns a stream consisting of the remaining elements of this stream
- * after indexing {@code startInclusive} elements into the stream and
- * truncated to contain no more than {@code endExclusive - startInclusive}
- * elements. If the {@code startInclusive} index lies past the end
- * of this stream then an empty stream will be returned.
+ * after discarding the first {@code startInclusive} elements and truncating
+ * the result to be no longer than {@code endExclusive - startInclusive}
+ * elements in length. If this stream contains fewer than
+ * {@code startInclusive} elements then an empty stream will be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* stateful intermediate operation</a>.
@@ -405,11 +449,23 @@
/**
* Returns an array containing the elements of this stream, using the
- * provided {@code generator} function to allocate the returned array.
+ * provided {@code generator} function to allocate the returned array, as
+ * well as any additional arrays that might be required for a partitioned
+ * execution or for resizing.
*
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
+ * @apiNote
+ * The generator function takes an integer, which is the size of the
+ * desired array, and produces an array of the desired size. This can be
+ * concisely expressed with an array constructor reference:
+ * <pre>{@code
+ * Person[] men = people.stream()
+ * .filter(p -> p.getGender() == MALE)
+ * .toArray(Person[]::new);
+ * }</pre>
+ *
* @param <A> the element type of the resulting array
* @param generator a function which produces a new array of the desired
* type and the provided length
@@ -451,7 +507,7 @@
* Integer sum = integers.reduce(0, (a, b) -> a+b);
* }</pre>
*
- * or more compactly:
+ * or:
*
* <pre>{@code
* Integer sum = integers.reduce(0, Integer::sum);
@@ -501,7 +557,8 @@
* @param accumulator an <a href="package-summary.html#Associativity">associative</a>
* <a href="package-summary.html#NonInterference">non-interfering,
* stateless</a> function for combining two values
- * @return the result of the reduction
+ * @return an {@link Optional} describing the result of the reduction
+ * @throws NullPointerException if the result of the reduction is null
* @see #reduce(Object, BinaryOperator)
* @see #min(java.util.Comparator)
* @see #max(java.util.Comparator)
@@ -511,7 +568,7 @@
/**
* Performs a <a href="package-summary.html#Reduction">reduction</a> on the
* elements of this stream, using the provided identity, accumulation
- * function, and a combining functions. This is equivalent to:
+ * function, and combining functions. This is equivalent to:
* <pre>{@code
* U result = identity;
* for (T element : this stream)
@@ -537,8 +594,8 @@
* by an explicit combination of {@code map} and {@code reduce} operations.
* The {@code accumulator} function acts as a fused mapper and accumulator,
* 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.
+ * such as when knowing the previously reduced value allows you to avoid
+ * some computation.
*
* @param <U> The type of the result
* @param identity the identity value for the combiner function
@@ -561,12 +618,12 @@
/**
* Performs a <a href="package-summary.html#MutableReduction">mutable
* reduction</a> operation on the elements of this stream. A mutable
- * reduction is one in which the reduced value is a mutable value holder,
+ * reduction is one in which the reduced value is a mutable result container,
* such as an {@code ArrayList}, and elements are incorporated by updating
- * the state of the result, rather than by replacing the result. This
+ * the state of the result rather than by replacing the result. This
* produces a result equivalent to:
* <pre>{@code
- * R result = resultFactory.get();
+ * R result = supplier.get();
* for (T element : this stream)
* accumulator.accept(result, element);
* return result;
@@ -579,10 +636,11 @@
* operation</a>.
*
* @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:
+ * well-suited for use with method references as arguments to {@code collect()}.
+ * For example, the following will accumulate strings into an {@code ArrayList}:
* <pre>{@code
- * List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
+ * List<String> asList = stringStream.collect(ArrayList::new, ArrayList::add,
+ * ArrayList::addAll);
* }</pre>
*
* <p>The following will take a stream of strings and concatenates them into a
@@ -594,10 +652,9 @@
* }</pre>
*
* @param <R> type of the result
- * @param resultFactory a 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 supplier a 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 an <a href="package-summary.html#Associativity">associative</a>
* <a href="package-summary.html#NonInterference">non-interfering,
* stateless</a> function for incorporating an additional
@@ -608,24 +665,24 @@
* must be compatible with the accumulator function
* @return the result of the reduction
*/
- <R> R collect(Supplier<R> resultFactory,
+ <R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
/**
* Performs a <a href="package-summary.html#MutableReduction">mutable
* reduction</a> operation on the elements of this stream using a
- * {@code Collector} object to describe the reduction. A {@code Collector}
+ * {@code Collector}. 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
+ * collection strategies and composition of collect operations such as
* multiple-level grouping or partitioning.
*
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
* <p>When executed in parallel, multiple intermediate results may be
- * instantiated, populated, and merged, so as to maintain isolation of
+ * instantiated, populated, and merged so as to maintain isolation of
* mutable data structures. Therefore, even when executed in parallel
* with non-thread-safe data structures (such as {@code ArrayList}), no
* additional synchronization is needed for a parallel reduction.
@@ -638,16 +695,16 @@
*
* <p>The following will classify {@code Person} objects by city:
* <pre>{@code
- * Map<String, Collection<Person>> peopleByCity
- * = personStream.collect(Collectors.groupBy(Person::getCity));
+ * Map<String, List<Person>> peopleByCity
+ * = personStream.collect(Collectors.groupingBy(Person::getCity));
* }</pre>
*
* <p>The following will classify {@code Person} objects by state and city,
* cascading two {@code Collector}s together:
* <pre>{@code
- * Map<String, Map<String, Collection<Person>>> peopleByStateAndCity
- * = personStream.collect(Collectors.groupBy(Person::getState,
- * Collectors.groupBy(Person::getCity)));
+ * Map<String, Map<String, List<Person>>> peopleByStateAndCity
+ * = personStream.collect(Collectors.groupingBy(Person::getState,
+ * Collectors.groupingBy(Person::getCity)));
* }</pre>
*
* @param <R> the type of the result
@@ -662,7 +719,7 @@
/**
* Returns the minimum element of this stream according to the provided
* {@code Comparator}. This is a special case of a
- * <a href="package-summary.html#MutableReduction">reduction</a>.
+ * <a href="package-summary.html#Reduction">reduction</a>.
*
* <p>This is a <a href="package-summary.html#StreamOps">terminal operation</a>.
*
@@ -671,13 +728,14 @@
* elements of this stream
* @return an {@code Optional} describing the minimum element of this stream,
* or an empty {@code Optional} if the stream is empty
+ * @throws NullPointerException if the minimum element is null
*/
Optional<T> min(Comparator<? super T> comparator);
/**
* Returns the maximum element of this stream according to the provided
* {@code Comparator}. This is a special case of a
- * <a href="package-summary.html#MutableReduction">reduction</a>.
+ * <a href="package-summary.html#Reduction">reduction</a>.
*
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
@@ -687,12 +745,13 @@
* elements of this stream
* @return an {@code Optional} describing the maximum element of this stream,
* or an empty {@code Optional} if the stream is empty
+ * @throws NullPointerException if the maximum element is null
*/
Optional<T> max(Comparator<? super T> comparator);
/**
* Returns the count of elements in this stream. This is a special case of
- * a <a href="package-summary.html#MutableReduction">reduction</a> and is
+ * a <a href="package-summary.html#Reduction">reduction</a> and is
* equivalent to:
* <pre>{@code
* return mapToLong(e -> 1L).sum();
@@ -753,10 +812,9 @@
boolean noneMatch(Predicate<? super T> predicate);
/**
- * Returns an {@link Optional} describing the first element of this stream
- * (in the encounter order), or an empty {@code Optional} if the stream is
- * empty. If the stream has no encounter order, then any element may be
- * returned.
+ * Returns an {@link Optional} describing the first element of this stream,
+ * or an empty {@code Optional} if the stream is empty. If the stream has
+ * no encounter order, then any element may be returned.
*
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>.
@@ -777,8 +835,8 @@
* <p>The behavior of this operation is explicitly nondeterministic; it is
* free to select any element in the stream. This is to allow for maximal
* performance in parallel operations; the cost is that multiple invocations
- * on the same source may not return the same result. (If the first element
- * in the encounter order is desired, use {@link #findFirst()} instead.)
+ * on the same source may not return the same result. (If a stable result
+ * is desired, use {@link #findFirst()} instead.)
*
* @return an {@code Optional} describing some element of this stream, or an
* empty {@code Optional} if the stream is empty
@@ -821,20 +879,20 @@
}
/**
- * Returns a sequential stream whose elements are the specified values.
+ * Returns a sequential ordered stream whose elements are the specified values.
*
* @param <T> the type of stream elements
* @param values the elements of the new stream
* @return the new stream
*/
@SafeVarargs
- @SuppressWarnings("varargs") // Creating a stream from an array is safe
+ @SuppressWarnings("varargs")
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
/**
- * Returns an infinite sequential {@code Stream} produced by iterative
+ * Returns an infinite sequential ordered {@code Stream} produced by iterative
* application of a function {@code f} to an initial element {@code seed},
* producing a {@code Stream} consisting of {@code seed}, {@code f(seed)},
* {@code f(f(seed))}, etc.
@@ -872,8 +930,8 @@
}
/**
- * Returns a sequential {@code Stream} where each element is
- * generated by a {@code Supplier}. This is suitable for generating
+ * Returns a sequential stream where each element is generated by
+ * the provided {@code Supplier}. This is suitable for generating
* constant streams, streams of random elements, etc.
*
* @param <T> the type of stream elements
@@ -887,17 +945,16 @@
}
/**
- * Creates a lazy concatenated {@code Stream} whose elements are all the
- * elements of a first {@code Stream} succeeded by all the elements of the
- * second {@code Stream}. The resulting stream is ordered if both
+ * Creates a lazily concatenated stream whose elements are all the
+ * elements of the first stream followed by all the elements of the
+ * second stream. The resulting stream is ordered if both
* of the input streams are ordered, and parallel if either of the input
* streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked.
*
* @param <T> The type of stream elements
* @param a the first stream
- * @param b the second stream to concatenate on to end of the first
- * stream
+ * @param b the second stream
* @return the concatenation of the two input streams
*/
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
@@ -917,7 +974,7 @@
* {@code Builder} (without the copying overhead that comes from using
* an {@code ArrayList} as a temporary buffer.)
*
- * <p>A {@code Stream.Builder} has a lifecycle, where it starts in a building
+ * <p>A stream builder has a lifecycle, which starts in a building
* phase, during which elements can be added, and then transitions to a built
* phase, after which elements may not be added. The built phase begins
* when the {@link #build()} method is called, which creates an ordered
--- a/jdk/src/share/classes/java/util/stream/StreamSpliterators.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/StreamSpliterators.java Fri Sep 06 22:20:01 2013 -0700
@@ -1456,4 +1456,5 @@
}
}
}
-}
\ No newline at end of file
+}
+
--- a/jdk/src/share/classes/java/util/stream/StreamSupport.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/StreamSupport.java Fri Sep 06 22:20:01 2013 -0700
@@ -32,12 +32,8 @@
* Low-level utility methods for creating and manipulating streams.
*
* <p>This class is mostly for library writers presenting stream views
- * of their data structures; most static stream methods for end users are in
- * {@link Streams}.
- *
- * <p>Unless otherwise stated, streams are created as sequential
- * streams. A sequential stream can be transformed into a parallel stream by
- * calling the {@code parallel()} method on the created stream.
+ * of data structures; most static stream methods intended for end users are in
+ * the various {@code Stream} classes.
*
* @since 1.8
*/
@@ -80,7 +76,7 @@
* {@code Supplier} of {@code Spliterator}.
*
* <p>The {@link Supplier#get()} method will be invoked on the supplier no
- * more than once, and after the terminal operation of the stream pipeline
+ * more than once, and only after the terminal operation of the stream pipeline
* commences.
*
* <p>For spliterators that report a characteristic of {@code IMMUTABLE}
@@ -88,7 +84,7 @@
* <a href="../Spliterator.html#binding">late-binding</a>, it is likely
* more efficient to use {@link #stream(java.util.Spliterator, boolean)}
* instead.
- * The use of a {@code Supplier} in this form provides a level of
+ * <p>The use of a {@code Supplier} in this form provides a level of
* indirection that reduces the scope of potential interference with the
* source. Since the supplier is only invoked after the terminal operation
* commences, any modifications to the source up to the start of the
@@ -148,7 +144,7 @@
* {@code Supplier} of {@code Spliterator.OfInt}.
*
* <p>The {@link Supplier#get()} method will be invoked on the supplier no
- * more than once, and after the terminal operation of the stream pipeline
+ * more than once, and only after the terminal operation of the stream pipeline
* commences.
*
* <p>For spliterators that report a characteristic of {@code IMMUTABLE}
@@ -156,7 +152,7 @@
* <a href="../Spliterator.html#binding">late-binding</a>, it is likely
* more efficient to use {@link #intStream(java.util.Spliterator.OfInt, boolean)}
* instead.
- * The use of a {@code Supplier} in this form provides a level of
+ * <p>The use of a {@code Supplier} in this form provides a level of
* indirection that reduces the scope of potential interference with the
* source. Since the supplier is only invoked after the terminal operation
* commences, any modifications to the source up to the start of the
@@ -215,7 +211,7 @@
* {@code Supplier} of {@code Spliterator.OfLong}.
*
* <p>The {@link Supplier#get()} method will be invoked on the supplier no
- * more than once, and after the terminal operation of the stream pipeline
+ * more than once, and only after the terminal operation of the stream pipeline
* commences.
*
* <p>For spliterators that report a characteristic of {@code IMMUTABLE}
@@ -223,7 +219,7 @@
* <a href="../Spliterator.html#binding">late-binding</a>, it is likely
* more efficient to use {@link #longStream(java.util.Spliterator.OfLong, boolean)}
* instead.
- * The use of a {@code Supplier} in this form provides a level of
+ * <p>The use of a {@code Supplier} in this form provides a level of
* indirection that reduces the scope of potential interference with the
* source. Since the supplier is only invoked after the terminal operation
* commences, any modifications to the source up to the start of the
@@ -282,7 +278,7 @@
* {@code Supplier} of {@code Spliterator.OfDouble}.
*
* <p>The {@link Supplier#get()} method will be invoked on the supplier no
- * more than once, and after the terminal operation of the stream pipeline
+ * more than once, and only after the terminal operation of the stream pipeline
* commences.
*
* <p>For spliterators that report a characteristic of {@code IMMUTABLE}
@@ -290,7 +286,7 @@
* <a href="../Spliterator.html#binding">late-binding</a>, it is likely
* more efficient to use {@link #doubleStream(java.util.Spliterator.OfDouble, boolean)}
* instead.
- * The use of a {@code Supplier} in this form provides a level of
+ * <p>The use of a {@code Supplier} in this form provides a level of
* indirection that reduces the scope of potential interference with the
* source. Since the supplier is only invoked after the terminal operation
* commences, any modifications to the source up to the start of the
--- a/jdk/src/share/classes/java/util/stream/package-info.java Thu Sep 12 13:20:26 2013 -0400
+++ b/jdk/src/share/classes/java/util/stream/package-info.java Fri Sep 06 22:20:01 2013 -0700
@@ -24,347 +24,484 @@
*/
/**
- * <h1>java.util.stream</h1>
- *
- * Classes to support functional-style operations on streams of values, as in the following:
+ * Classes to support functional-style operations on streams of elements, such
+ * as map-reduce transformations on collections. For example:
*
* <pre>{@code
- * int sumOfWeights = blocks.stream().filter(b -> b.getColor() == RED)
- * .mapToInt(b -> b.getWeight())
- * .sum();
+ * int sum = widgets.stream()
+ * .filter(b -> b.getColor() == RED)
+ * .mapToInt(b -> b.getWeight())
+ * .sum();
* }</pre>
*
- * <p>Here we use {@code blocks}, which might be a {@code Collection}, as a source for a stream,
- * and then perform a filter-map-reduce ({@code sum()} is an example of a <a href="package-summary.html#Reduction">reduction</a>
- * operation) on the stream to obtain the sum of the weights of the red blocks.
+ * <p>Here we use {@code widgets}, a {@code Collection<Widget>},
+ * as a source for a stream, and then perform a filter-map-reduce on the stream
+ * to obtain the sum of the weights of the red widgets. (Summation is an
+ * example of a <a href="package-summary.html#Reduction">reduction</a>
+ * operation.)
*
- * <p>The key abstraction used in this approach is {@link java.util.stream.Stream}, as well as its primitive
- * specializations {@link java.util.stream.IntStream}, {@link java.util.stream.LongStream},
- * and {@link java.util.stream.DoubleStream}. Streams differ from Collections in several ways:
+ * <p>The key abstraction introduced in this package is <em>stream</em>. The
+ * classes {@link java.util.stream.Stream}, {@link java.util.stream.IntStream},
+ * {@link java.util.stream.LongStream}, and {@link java.util.stream.DoubleStream}
+ * are streams over objects and the primitive {@code int}, {@code long} and
+ * {@code double} types. Streams differ from collections in several ways:
*
* <ul>
- * <li>No storage. A stream is not a data structure that stores elements; instead, they
- * carry values from a source (which could be a data structure, a generator, an IO channel, etc)
- * through a pipeline of computational operations.</li>
- * <li>Functional in nature. An operation on a stream produces a result, but does not modify
- * its underlying data source. For example, filtering a {@code Stream} produces a new {@code Stream},
- * rather than removing elements from the underlying source.</li>
- * <li>Laziness-seeking. Many stream operations, such as filtering, mapping, or duplicate removal,
- * can be implemented lazily, exposing opportunities for optimization. (For example, "find the first
- * {@code String} matching a pattern" need not examine all the input strings.) Stream operations
- * are divided into intermediate ({@code Stream}-producing) operations and terminal (value-producing)
- * operations; all intermediate operations are lazy.</li>
- * <li>Possibly unbounded. While collections have a finite size, streams need not. Operations
- * such as {@code limit(n)} or {@code findFirst()} can allow computations on infinite streams
- * to complete in finite time.</li>
+ * <li>No storage. A stream is not a data structure that stores elements;
+ * instead, it conveys elements from a source such as a data structure,
+ * an array, a generator function, or an I/O channel, through a pipeline of
+ * computational operations.</li>
+ * <li>Functional in nature. An operation on a stream produces a result,
+ * but does not modify its source. For example, filtering a {@code Stream}
+ * obtained from a collection produces a new {@code Stream} without the
+ * filtered elements, rather than removing elements from the source
+ * collection.</li>
+ * <li>Laziness-seeking. Many stream operations, such as filtering, mapping,
+ * or duplicate removal, can be implemented lazily, exposing opportunities
+ * for optimization. For example, "find the first {@code String} with
+ * three consecutive vowels" need not examine all the input strings.
+ * Stream operations are divided into intermediate ({@code Stream}-producing)
+ * operations and terminal (value- or side-effect-producing) operations.
+ * Intermediate operations are always lazy.</li>
+ * <li>Possibly unbounded. While collections have a finite size, streams
+ * need not. Short-circuting operations such as {@code limit(n)} or
+ * {@code findFirst()} can allow computations on infinite streams to
+ * complete in finite time.</li>
+ * <li>Consumable. The elements of a stream are only visited once during
+ * the life of a stream. Like an {@link java.util.Iterator}, a new stream
+ * must be generated to revisit the same elements of the source.
+ * </li>
+ * </ul>
+ *
+ * Streams can be obtained in a number of ways. Some examples include:
+ * <ul>
+ * <li>From a {@link java.util.Collection} via the {@code stream()} and
+ * {@code parallelStream()} methods;</li>
+ * <li>From an array via {@link java.util.Arrays#stream(Object[])};</li>
+ * <li>From static factory methods on the stream classes, such as
+ * {@link java.util.stream.Stream#of(Object[])},
+ * {@link java.util.stream.IntStream#range(int, int)}
+ * or {@link java.util.stream.Stream#iterate(Object, UnaryOperator)};</li>
+ * <li>The lines of a file can be obtained from {@link java.io.BufferedReader#lines()};</li>
+ * <li>Streams of file paths can be obtained from methods in {@link java.nio.file.Files};</li>
+ * <li>Streams of random numbers can be obtained from {@link java.util.Random#ints()};</li>
+ * <li>Numerous other stream-bearing methods in the JDK, including
+ * {@link java.util.BitSet#stream()},
+ * {@link java.util.regex.Pattern#splitAsStream(java.lang.CharSequence)},
+ * and {@link java.util.jar.JarFile#stream()}.</li>
* </ul>
*
- * <h2><a name="StreamPipelines">Stream pipelines</a></h2>
+ * <p>Additional stream sources can be provided by third-party libraries using
+ * <a href="package-summary.html#StreamSources">these techniques</a>.
+ *
+ * <h2><a name="StreamOps">Stream operations and pipelines</a></h2>
*
- * <p>Streams are used to create <em>pipelines</em> of <a href="package-summary.html#StreamOps">operations</a>. A
- * complete stream pipeline has several components: a source (which may be a {@code Collection},
- * an array, a generator function, or an IO channel); zero or more <em>intermediate operations</em>
- * such as {@code Stream.filter} or {@code Stream.map}; and a <em>terminal operation</em> such
- * as {@code Stream.forEach} or {@code java.util.stream.Stream.reduce}. Stream operations may take as parameters
- * <em>function values</em> (which are often lambda expressions, but could be method references
- * or objects) which parameterize the behavior of the operation, such as a {@code Predicate}
- * passed to the {@code Stream#filter} method.
+ * <p>Stream <a href="package-summary.html#StreamOps">operations</a> are
+ * divided into <em>intermediate</em> and <em>terminal</em> operations, and are
+ * combined to form <em>stream pipelines</em>. A stream pipeline consists of a
+ * source (such as a {@code Collection}, an array, a generator function, or an
+ * I/O channel); followed by zero or more intermediate operations such
+ * as {@code Stream.filter} or {@code Stream.map}; and a terminal
+ * operation such as {@code Stream.forEach} or {@code Stream.reduce}.
*
- * <p>Intermediate operations return a new {@code Stream}. They are lazy; executing an
- * intermediate operation such as {@link java.util.stream.Stream#filter Stream.filter} does
- * not actually perform any filtering, instead creating a new {@code Stream} that, when
- * traversed, contains the elements of the initial {@code Stream} that match the
- * given {@code Predicate}. Consuming elements from the stream source does not
- * begin until the terminal operation is executed.
+ * <p>Intermediate operations return a new stream. They are always
+ * <em>lazy</em>; executing an intermediate operation such as
+ * {@code filter()} does not actually perform any filtering, but instead
+ * creates a new stream that, when traversed, contains the elements of
+ * the initial stream that match the given predicate. Traversal
+ * of the pipeline source does not begin until the terminal operation of the
+ * pipeline is executed.
*
- * <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 and you must
- * return to the data source, or select a new data source, to get a new stream. For example,
- * obtaining the sum of weights of all red blocks, and then of all blue blocks, requires a
- * filter-map-reduce on two different streams:
- * <pre>{@code
- * int sumOfRedWeights = blocks.stream().filter(b -> b.getColor() == RED)
- * .mapToInt(b -> b.getWeight())
- * .sum();
- * int sumOfBlueWeights = blocks.stream().filter(b -> b.getColor() == BLUE)
- * .mapToInt(b -> b.getWeight())
- * .sum();
- * }</pre>
- *
- * <p>However, there are other techniques that allow you to obtain both results in a single
- * pass if multiple traversal is impractical or inefficient. TODO provide link
+ * <p>Terminal operations, such as {@code Stream.forEach} or
+ * {@code IntStream.sum}, may traverse the stream to produce a result or a
+ * side-effect. After the terminal operation is performed, the stream pipeline
+ * is considered consumed, and can no longer be used; if you need to traverse
+ * the same data source again, you must return to the data source to get a new
+ * stream. In almost all cases, terminal operations are <em>eager</em>,
+ * completing their traversal of the data source and processing of the pipeline
+ * before returning. Only the terminal operations {@code iterator()} and
+ * {@code spliterator()} are not; these are provided as an "escape hatch" to enable
+ * arbitrary client-controlled pipeline traversals in the event that the
+ * existing operations are not sufficient to the task.
*
- * <h3><a name="StreamOps">Stream operations</a></h3>
- *
- * <p>Intermediate stream operation (such as {@code filter} or {@code sorted}) always produce a
- * new {@code Stream}, and are always<em>lazy</em>. Executing a lazy operations does not
- * trigger processing of the stream contents; all processing is deferred until the terminal
- * operation commences. Processing streams lazily allows for significant efficiencies; in a
- * pipeline such as the filter-map-sum example above, filtering, mapping, and addition can be
- * fused into a single pass, with minimal intermediate state. Laziness also enables us to avoid
- * examining all the data when it is not necessary; for operations such as "find the first
- * string longer than 1000 characters", one need not examine all the input strings, just enough
- * to find one that has the desired characteristics. (This behavior becomes even more important
- * when the input stream is infinite and not merely large.)
+ * <p> Processing streams lazily allows for significant efficiencies; in a
+ * pipeline such as the filter-map-sum example above, filtering, mapping, and
+ * summing can be fused into a single pass on the data, with minimal
+ * intermediate state. Laziness also allows avoiding examining all the data
+ * when it is not necessary; for operations such as "find the first string
+ * longer than 1000 characters", it is only necessary to examine just enough
+ * strings to find one that has the desired characteristics without examining
+ * all of the strings available from the source. (This behavior becomes even
+ * more important when the input stream is infinite and not merely large.)
*
- * <p>Intermediate operations are further divided into <em>stateless</em> and <em>stateful</em>
- * operations. Stateless operations retain no state from previously seen values when processing
- * a new value; examples of stateless intermediate operations include {@code filter} and
- * {@code map}. Stateful operations may incorporate state from previously seen elements in
- * processing new values; examples of stateful intermediate operations include {@code distinct}
- * and {@code sorted}. Stateful operations may need to process the entire input before
- * producing a result; for example, one cannot produce any results from sorting a stream until
- * one has seen all elements of the stream. As a result, under parallel computation, some
- * pipelines containing stateful intermediate operations have to be executed in multiple passes.
- * Pipelines containing exclusively stateless intermediate operations can be processed in a
- * single pass, whether sequential or parallel.
+ * <p>Intermediate operations are further divided into <em>stateless</em>
+ * and <em>stateful</em> operations. Stateless operations, such as {@code filter}
+ * and {@code map}, retain no state from previously seen element when processing
+ * a new element -- each element can be processed
+ * independently of operations on other elements. Stateful operations, such as
+ * {@code distinct} and {@code sorted}, may incorporate state from previously
+ * seen elements when processing new elements.
*
- * <p>Further, some operations are deemed <em>short-circuiting</em> operations. An intermediate
- * operation is short-circuiting if, when presented with infinite input, it may produce a
- * finite stream as a result. A terminal operation is short-circuiting if, when presented with
- * infinite input, it may terminate in finite time. (Having a short-circuiting operation is a
- * necessary, but not sufficient, condition for the processing of an infinite stream to
- * terminate normally in finite time.)
+ * <p>Stateful operations may need to process the entire input
+ * before producing a result. For example, one cannot produce any results from
+ * sorting a stream until one has seen all elements of the stream. As a result,
+ * under parallel computation, some pipelines containing stateful intermediate
+ * operations may require multiple passes on the data or may need to buffer
+ * significant data. Pipelines containing exclusively stateless intermediate
+ * operations can be processed in a single pass, whether sequential or parallel,
+ * with minimal data buffering.
*
- * Terminal operations (such as {@code forEach} or {@code findFirst}) are always eager
- * (they execute completely before returning), and produce a non-{@code Stream} result, such
- * as a primitive value or a {@code Collection}, or have side-effects.
+ * <p>Further, some operations are deemed <em>short-circuiting</em> operations.
+ * An intermediate operation is short-circuiting if, when presented with
+ * infinite input, it may produce a finite stream as a result. A terminal
+ * operation is short-circuiting if, when presented with infinite input, it may
+ * terminate in finite time. Having a short-circuiting operation in the pipeline
+ * is a necessary, but not sufficient, condition for the processing of an infinite
+ * stream to terminate normally in finite time.
*
* <h3>Parallelism</h3>
*
- * <p>By recasting aggregate operations as a pipeline of operations on a stream of values, many
- * aggregate operations can be more easily parallelized. A {@code Stream} can execute either
- * in serial or in parallel. When streams are created, they are either created as sequential
- * or parallel streams; the parallel-ness of streams can also be switched by the
- * {@link java.util.stream Stream#sequential()} and {@link java.util.stream.Stream#parallel()}
- * operations. The {@code Stream} implementations in the JDK create serial streams unless
- * parallelism is explicitly requested. For example, {@code Collection} has methods
+ * <p>Processing elements with an explicit {@code for-}loop is inherently serial.
+ * Streams facilitate parallel execution by reframing the computation as a pipeline of
+ * aggregate operations, rather than as imperative operations on each individual
+ * element. All streams operations can execute either in serial or in parallel.
+ * The stream implementations in the JDK create serial streams unless parallelism is
+ * explicitly requested. For example, {@code Collection} has methods
* {@link java.util.Collection#stream} and {@link java.util.Collection#parallelStream},
- * which produce sequential and parallel streams respectively; other stream-bearing methods
- * such as {@link java.util.stream.IntStream#range(int, int)} produce sequential
- * streams but these can be efficiently parallelized by calling {@code parallel()} on the
- * result. The set of operations on serial and parallel streams is identical. To execute the
- * "sum of weights of blocks" query in parallel, we would do:
+ * which produce sequential and parallel streams respectively; other
+ * stream-bearing methods such as {@link java.util.stream.IntStream#range(int, int)}
+ * produce sequential streams but these streams can be efficiently parallelized by
+ * invoking their {@link java.util.stream.BaseStream#parallel()} method.
+ * To execute the prior "sum of weights of widgets" query in parallel, we would
+ * do:
*
* <pre>{@code
- * int sumOfWeights = blocks.parallelStream().filter(b -> b.getColor() == RED)
- * .mapToInt(b -> b.getWeight())
- * .sum();
+ * int sumOfWeights = widgets.}<b>{@code parallelStream()}</b>{@code .filter(b -> b.getColor() == RED)
+ * .mapToInt(b -> b.getWeight())
+ * .sum();
* }</pre>
*
- * <p>The only difference between the serial and parallel versions of this example code is
- * the creation of the initial {@code Stream}. Whether a {@code Stream} will execute in serial
- * or parallel can be determined by the {@code Stream#isParallel} method. When the terminal
- * operation is initiated, the entire stream pipeline is either executed sequentially or in
- * parallel, determined by the last operation that affected the stream's serial-parallel
- * orientation (which could be the stream source, or the {@code sequential()} or
- * {@code parallel()} methods.)
- *
- * <p>In order for the results of parallel operations to be deterministic and consistent with
- * their serial equivalent, the function values passed into the various stream operations should
- * be <a href="#NonInteference"><em>stateless</em></a>.
- *
- * <h3><a name="Ordering">Ordering</a></h3>
- *
- * <p>Streams may or may not have an <em>encounter order</em>. An encounter
- * order specifies the order in which elements are provided by the stream to the
- * operations pipeline. Whether or not there is an encounter order depends on
- * the source, the intermediate operations, and the terminal operation.
- * Certain stream sources (such as {@code List} or arrays) are intrinsically
- * ordered, whereas others (such as {@code HashSet}) are not. Some intermediate
- * operations may impose an encounter order on an otherwise unordered stream,
- * such as {@link java.util.stream.Stream#sorted()}, and others may render an
- * ordered stream unordered (such as {@link java.util.stream.Stream#unordered()}).
- * Some terminal operations may ignore encounter order, such as
- * {@link java.util.stream.Stream#forEach}.
+ * <p>The only difference between the serial and parallel versions of this
+ * example is the creation of the initial stream, using "{@code parallelStream()}"
+ * instead of "{@code stream()}". When the terminal operation is initiated,
+ * the stream pipeline is executed sequentially or in parallel depending on the
+ * orientation of the stream on which it is invoked. Whether a stream will execute in serial or
+ * parallel can be determined with the {@code isParallel()} method, and the
+ * orientation of a stream can be modified with the
+ * {@link java.util.stream.BaseStream#sequential()} and
+ * {@link java.util.stream.BaseStream#parallel()} operations. When the terminal
+ * operation is initiated, the stream pipeline is executed sequentially or in
+ * parallel depending on the mode of the stream on which it is invoked.
*
- * <p>If a Stream is ordered, most operations are constrained to operate on the
- * elements in their encounter order; if the source of a stream is a {@code List}
- * containing {@code [1, 2, 3]}, then the result of executing {@code map(x -> x*2)}
- * must be {@code [2, 4, 6]}. However, if the source has no defined encounter
- * order, than any of the six permutations of the values {@code [2, 4, 6]} would
- * be a valid result. Many operations can still be efficiently parallelized even
- * under ordering constraints.
- *
- * <p>For sequential streams, ordering is only relevant to the determinism
- * of operations performed repeatedly on the same source. (An {@code ArrayList}
- * is constrained to iterate elements in order; a {@code HashSet} is not, and
- * repeated iteration might produce a different order.)
+ * <p>Except for operations identified as explicitly nondeterministic, such
+ * as {@code findAny()}, whether a stream executes sequentially or in parallel
+ * should not change the result of the computation.
*
- * <p>For parallel streams, relaxing the ordering constraint can enable
- * optimized implementation for some operations. For example, duplicate
- * filtration on an ordered stream must completely process the first partition
- * before it can return any elements from a subsequent partition, even if those
- * elements are available earlier. On the other hand, without the constraint of
- * ordering, duplicate filtration can be done more efficiently by using
- * a shared {@code ConcurrentHashSet}. There will be cases where the stream
- * is structurally ordered (the source is ordered and the intermediate
- * operations are order-preserving), but the user does not particularly care
- * about the encounter order. In some cases, explicitly de-ordering the stream
- * with the {@link java.util.stream.Stream#unordered()} method may result in
- * improved parallel performance for some stateful or terminal operations.
+ * <p>Most stream operations accept parameters that describe user-specified
+ * behavior, which are often lambda expressions. To preserve correct behavior,
+ * these <em>behavioral parameters</em> must be <em>non-interfering</em>, and in
+ * most cases must be <em>stateless</em>. 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.
*
* <h3><a name="Non-Interference">Non-interference</a></h3>
*
- * The {@code java.util.stream} package enables you to execute possibly-parallel
- * bulk-data operations over a variety of data sources, including even non-thread-safe
- * collections such as {@code ArrayList}. This is possible only if we can
- * prevent <em>interference</em> with the data source during the execution of a
- * stream pipeline. (Execution begins when the terminal operation is invoked, and ends
- * when the terminal operation completes.) For most data sources, preventing interference
- * means ensuring that the data source is <em>not modified at all</em> during the execution
- * of the stream pipeline. (Some data sources, such as concurrent collections, are
- * specifically designed to handle concurrent modification.)
+ * Streams enable you to execute possibly-parallel aggregate operations over a
+ * variety of data sources, including even non-thread-safe collections such as
+ * {@code ArrayList}. This is possible only if we can prevent
+ * <em>interference</em> with the data source during the execution of a stream
+ * pipeline. Except for the escape-hatch operations {@code iterator()} and
+ * {@code spliterator()}, execution begins when the terminal operation is
+ * invoked, and ends when the terminal operation completes. For most data
+ * sources, preventing interference means ensuring that the data source is
+ * <em>not modified at all</em> during the execution of the stream pipeline.
+ * The notable exception to this are streams whose sources are concurrent
+ * collections, which are specifically designed to handle concurrent modification.
*
- * <p>Accordingly, lambda expressions (or other objects implementing the appropriate functional
- * interface) passed to stream methods should never modify the stream's data source. An
- * implementation is said to <em>interfere</em> with the data source if it modifies, or causes
- * to be modified, the stream's data source. The need for non-interference applies to all
- * pipelines, not just parallel ones. Unless the stream source is concurrent, modifying a
- * stream's data source during execution of a stream pipeline can cause exceptions, incorrect
- * answers, or nonconformant results.
+ * <p>Accordingly, behavioral parameters passed to stream methods should never
+ * modify the stream's data source. An implementation is said to
+ * <em>interfere</em> with the data source if it modifies, or causes to be
+ * modified, the stream's data source. The need for non-interference applies
+ * to all pipelines, not just parallel ones. Unless the stream source is
+ * concurrent, modifying a stream's data source during execution of a stream
+ * pipeline can cause exceptions, incorrect answers, or nonconformant behavior.
*
- * <p>Further, results may be nondeterministic or incorrect if the lambda expressions passed to
- * stream operations are <em>stateful</em>. A stateful lambda (or other object implementing the
- * appropriate functional interface) is one whose result depends on any state which might change
- * during the execution of the stream pipeline. An example of a stateful lambda is:
+ * <p>Results may be nondeterministic or incorrect if the behavioral
+ * parameters of stream operations are <em>stateful</em>. A stateful lambda
+ * (or other object implementing the appropriate functional interface) is one
+ * whose result depends on any state which might change during the execution
+ * of the stream pipeline. An example of a stateful lambda is:
+ *
* <pre>{@code
* Set<Integer> seen = Collections.synchronizedSet(new HashSet<>());
* stream.parallel().map(e -> { if (seen.add(e)) return 0; else return e; })...
* }</pre>
- * Here, if the mapping operation is performed in parallel, the results for the same input
- * could vary from run to run, due to thread scheduling differences, whereas, with a stateless
- * lambda expression the results would always be the same.
+ *
+ * Here, if the mapping operation is performed in parallel, the results for the
+ * same input could vary from run to run, due to thread scheduling differences,
+ * whereas, with a stateless lambda expression the results would always be the
+ * same.
+ *
+ * For well-behaved stream sources, the source can be modified before the
+ * terminal operation commences and those modifications will be reflected in
+ * the covered elements. For example, consider the following code:
+ *
+ * <pre>{@code
+ * List<String> l = new ArrayList(Arrays.asList("one", "two"));
+ * Stream<String> sl = l.stream();
+ * l.add("three");
+ * String s = sl.collect(joining(" "));
+ * }</pre>
+ *
+ * First a list is created consisting of two strings: "one"; and "two". Then a
+ * stream is created from that list. Next the list is modified by 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". All the
+ * streams returned from JDK collections, and most other JDK classes,
+ * are well-behaved in this manner; for streams generated by other libraries, see
+ * <a href="package-summary.html#StreamSources">Low-level stream
+ * construction</a> for requirements for building well-behaved streams.
+ *
+ * <p>Some streams, particularly those whose stream sources are concurrent, can
+ * tolerate concurrent modification during execution of a stream pipeline.
+ * However, in no case -- even if the stream source is concurrent -- should
+ * behavioral parameters to stream operations modify the stream source. Modifying
+ * the stream source from within the stream source may cause pipeline execution
+ * to fail to terminate, produce inaccurate results, or throw exceptions.
+ * The following example shows inappropriate interference with the source:
+ * <pre>{@code
+ * // Don't do this!
+ * List<String> l = new ArrayList(Arrays.asList("one", "two"));
+ * Stream<String> sl = l.stream();
+ * String s = sl.peek(s -> l.add("BAD LAMBDA")).collect(joining(" "));
+ * }</pre>
*
* <h3>Side-effects</h3>
*
+ * Side-effects in behavioral parameters to stream operations are, in general,
+ * discouraged, as they can often lead to unwitting violations of the
+ * statelessness requirement, as well as other thread-safety hazards. Many
+ * computations where one might be tempted to use side effects can be more
+ * safely and efficiently expressed without side-effects, such as using
+ * <a href="package-summary.html#Reduction">reduction</a> instead of mutable
+ * accumulators. However, side-effects such as using {@code println()} for debugging
+ * purposes are usually harmless. A small number of stream operations, such as
+ * {@code forEach()} and {@code peek()}, can operate only via side-effects;
+ * these should be used with care.
+ *
+ * <p>As an example of how to transform a stream pipeline that inappropriately
+ * uses side-effects to one that does not, the following code searches a stream
+ * of strings for those matching a given regular expression, and puts the
+ * matches in a list.
+ *
+ * <pre>{@code
+ * ArrayList<String> results = new ArrayList<>();
+ * stream.filter(s -> pattern.matcher(s).matches())
+ * .forEach(s -> results.add(s)); // Unnecessary use of side-effects!
+ * }</pre>
+ *
+ * This code unnecessarily uses side-effects. If executed in parallel, the
+ * non-thread-safety of {@code ArrayList} would cause incorrect results, and
+ * adding needed synchronization would cause contention, undermining the
+ * benefit of parallelism. Furthermore, using side-effects here is completely
+ * unnecessary; the {@code forEach()} can simply be replaced with a reduction
+ * operation that is safer, more efficient, and more amenable to
+ * parallelization:
+ *
+ * <pre>{@code
+ * List<String>results =
+ * stream.filter(s -> pattern.matcher(s).matches())
+ * .collect(Collectors.toList()); // No side-effects!
+ * }</pre>
+ *
+ * <h3><a name="Ordering">Ordering</a></h3>
+ *
+ * <p>Streams may or may not have a defined <em>encounter order</em>. Whether
+ * or not a stream has an encounter order depends on the source and the
+ * intermediate operations. Certain stream sources (such as {@code List} or
+ * arrays) are intrinsically ordered, whereas others (such as {@code HashSet})
+ * are not. Some intermediate operations, such as {@code sorted()}, may impose
+ * an encounter order on an otherwise unordered stream, and others may render an
+ * ordered stream unordered, such as {@link java.util.stream.BaseStream#unordered()}.
+ * Further, some terminal operations may ignore encounter order, such as
+ * {@code forEach()}.
+ *
+ * <p>If a stream is ordered, most operations are constrained to operate on the
+ * elements in their encounter order; if the source of a stream is a {@code List}
+ * containing {@code [1, 2, 3]}, then the result of executing {@code map(x -> x*2)}
+ * must be {@code [2, 4, 6]}. However, if the source has no defined encounter
+ * order, then any permutation of the values {@code [2, 4, 6]} would be a valid
+ * result.
+ *
+ * <p>For sequential streams, the presence or absence of an encounter order does
+ * not affect performance, only determinism. If a stream is ordered, repeated
+ * execution of identical stream pipelines on an identical source will produce
+ * an identical result; if it is not ordered, repeated execution might produce
+ * different results.
+ *
+ * <p>For parallel streams, relaxing the ordering constraint can sometimes enable
+ * more efficient execution. Certain aggregate operations,
+ * such as filtering duplicates ({@code distinct()}) or grouped reductions
+ * ({@code Collectors.groupingBy()}) can be implemented more efficiently if ordering of elements
+ * is not relevant. Similarly, operations that are intrinsically tied to encounter order,
+ * such as {@code limit()}, may require
+ * buffering to ensure proper ordering, undermining the benefit of parallelism.
+ * In cases where the stream has an encounter order, but the user does not
+ * particularly <em>care</em> about that encounter order, explicitly de-ordering
+ * the stream with {@link java.util.stream.BaseStream#unordered() unordered()} may
+ * improve parallel performance for some stateful or terminal operations.
+ * However, most stream pipelines, such as the "sum of weight of blocks" example
+ * above, still parallelize efficiently even under ordering constraints.
+ *
* <h2><a name="Reduction">Reduction operations</a></h2>
*
- * A <em>reduction</em> operation takes a stream of elements and processes them in a way
- * that reduces to a single value or summary description, such as finding the sum or maximum
- * of a set of numbers. (In more complex scenarios, the reduction operation might need to
- * extract data from the elements before reducing that data to a single value, such as
- * finding the sum of weights of a set of blocks. This would require extracting the weight
- * from each block before summing up the weights.)
+ * A <em>reduction</em> operation (also called a <em>fold</em>) takes a sequence
+ * of input elements and combines them into a single summary result by repeated
+ * application of a combining operation, such as finding the sum or maximum of
+ * a set of numbers, or accumulating elements into a list. The streams classes have
+ * multiple forms of general reduction operations, called
+ * {@link java.util.stream.Stream#reduce(java.util.function.BinaryOperator) reduce()}
+ * and {@link java.util.stream.Stream#collect(java.util.stream.Collector) collect()},
+ * as well as multiple specialized reduction forms such as
+ * {@link java.util.stream.IntStream#sum() sum()}, {@link java.util.stream.IntStream#max() max()},
+ * or {@link java.util.stream.IntStream#count() count()}.
*
- * <p>Of course, such operations can be readily implemented as simple sequential loops, as in:
+ * <p>Of course, such operations can be readily implemented as simple sequential
+ * loops, as in:
* <pre>{@code
* int sum = 0;
* for (int x : numbers) {
* sum += x;
* }
* }</pre>
- * However, there may be a significant advantage to preferring a {@link java.util.stream.Stream#reduce reduce operation}
- * over a mutative accumulation such as the above -- a properly constructed reduce operation is
- * inherently parallelizable so long as the
- * {@link java.util.function.BinaryOperator reduction operaterator}
- * has the right characteristics. Specifically the operator must be
- * <a href="#Associativity">associative</a>. For example, given a
- * stream of numbers for which we want to find the sum, we can write:
+ * However, there are good reasons to prefer a reduce operation
+ * over a mutative accumulation such as the above. Not only is a reduction
+ * "more abstract" -- it operates on the stream as a whole rather than individual
+ * elements -- but a properly constructed reduce operation is inherently
+ * parallelizable, so long as the function(s) used to process the elements
+ * are <a href="package-summary.html#Associativity">associative</a> and
+ * <a href="package-summary.html#NonInterfering">stateless</a>.
+ * For example, given a stream of numbers for which we want to find the sum, we
+ * can write:
* <pre>{@code
- * int sum = numbers.reduce(0, (x,y) -> x+y);
+ * int sum = numbers.stream().reduce(0, (x,y) -> x+y);
* }</pre>
- * or more succinctly:
+ * or:
* <pre>{@code
- * int sum = numbers.reduce(0, Integer::sum);
+ * int sum = numbers.stream().reduce(0, Integer::sum);
* }</pre>
*
- * <p>(The primitive specializations of {@link java.util.stream.Stream}, such as
- * {@link java.util.stream.IntStream}, even have convenience methods for common reductions,
- * such as {@link java.util.stream.IntStream#sum() sum} and {@link java.util.stream.IntStream#max() max},
- * which are implemented as simple wrappers around reduce.)
+ * <p>These reduction operations can run safely in parallel with almost no
+ * modification:
+ * <pre>{@code
+ * int sum = numbers.parallelStream().reduce(0, Integer::sum);
+ * }</pre>
*
- * <p>Reduction parallellizes well since the implementation of {@code reduce} can operate on
- * subsets of the stream in parallel, and then combine the intermediate results to get the final
- * correct answer. Even if you were to use a parallelizable form of the
- * {@link java.util.stream.Stream#forEach(Consumer) forEach()} method
- * in place of the original for-each loop above, you would still have to provide thread-safe
- * updates to the shared accumulating variable {@code sum}, and the required synchronization
- * would likely eliminate any performance gain from parallelism. Using a {@code reduce} method
- * instead removes all of the burden of parallelizing the reduction operation, and the library
- * can provide an efficient parallel implementation with no additional synchronization needed.
+ * <p>Reduction parallellizes well because the implementation
+ * can operate on subsets of the data in parallel, and then combine the
+ * intermediate results to get the final correct answer. (Even if the language
+ * had a "parallel for-each" construct, the mutative accumulation approach would
+ * still required the developer to provide
+ * thread-safe updates to the shared accumulating variable {@code sum}, and
+ * the required synchronization would then likely eliminate any performance gain from
+ * parallelism.) Using {@code reduce()} instead removes all of the
+ * burden of parallelizing the reduction operation, and the library can provide
+ * an efficient parallel implementation with no additional synchronization
+ * required.
*
- * <p>The "blocks" examples shown earlier shows how reduction combines with other operations
- * to replace for loops with bulk operations. If {@code blocks} is a collection of {@code Block}
- * objects, which have a {@code getWeight} method, we can find the heaviest block with:
+ * <p>The "widgets" examples shown earlier shows how reduction combines with
+ * other operations to replace for loops with bulk operations. If {@code widgets}
+ * is a collection of {@code Widget} objects, which have a {@code getWeight} method,
+ * we can find the heaviest widget with:
* <pre>{@code
- * OptionalInt heaviest = blocks.stream()
- * .mapToInt(Block::getWeight)
- * .reduce(Integer::max);
+ * OptionalInt heaviest = widgets.parallelStream()
+ * .mapToInt(Widget::getWeight)
+ * .max();
* }</pre>
*
- * <p>In its more general form, a {@code reduce} operation on elements of type {@code <T>}
- * yielding a result of type {@code <U>} requires three parameters:
+ * <p>In its more general form, a {@code reduce} operation on elements of type
+ * {@code <T>} yielding a result of type {@code <U>} requires three parameters:
* <pre>{@code
* <U> U reduce(U identity,
- * BiFunction<U, ? super T, U> accumlator,
+ * BiFunction<U, ? super T, U> accumulator,
* BinaryOperator<U> combiner);
* }</pre>
- * Here, the <em>identity</em> element is both an initial seed for the reduction, and a default
- * result if there are no elements. The <em>accumulator</em> function takes a partial result and
- * the next element, and produce a new partial result. The <em>combiner</em> function combines
- * the partial results of two accumulators to produce a new partial result, and eventually the
- * final result.
+ * Here, the <em>identity</em> element is both an initial seed value for the reduction
+ * and a default result if there are no input elements. The <em>accumulator</em>
+ * function takes a partial result and the next element, and produces a new
+ * partial result. The <em>combiner</em> function combines two partial results
+ * to produce a new partial result. (The combiner is necessary in parallel
+ * reductions, where the input is partitioned, a partial accumulation computed
+ * for each partition, and then the partial results are combined to produce a
+ * final result.)
*
- * <p>This form is a generalization of the two-argument form, and is also a generalization of
- * the map-reduce construct illustrated above. If we wanted to re-cast the simple {@code sum}
- * example using the more general form, {@code 0} would be the identity element, while
- * {@code Integer::sum} would be both the accumulator and combiner. For the sum-of-weights
- * example, this could be re-cast as:
+ * <p>More formally, the {@code identity} value must be an <em>identity</em> for
+ * the combiner function. This means that for all {@code u},
+ * {@code combiner.apply(identity, u)} is equal to {@code u}. Additionally, the
+ * {@code combiner} function must be <a href="package-summary.html#Associativity">associative</a> and
+ * must be compatible with the {@code accumulator} function: for all {@code u}
+ * and {@code t}, {@code combiner.apply(u, accumulator.apply(identity, t))} must
+ * be {@code equals()} to {@code accumulator.apply(u, t)}.
+ *
+ * <p>The three-argument form is a generalization of the two-argument form,
+ * incorporating a mapping step into the accumulation step. We could
+ * re-cast the simple sum-of-weights example using the more general form as
+ * follows:
* <pre>{@code
- * int sumOfWeights = blocks.stream().reduce(0,
- * (sum, b) -> sum + b.getWeight())
- * Integer::sum);
+ * int sumOfWeights = widgets.stream()
+ * .reduce(0,
+ * (sum, b) -> sum + b.getWeight())
+ * Integer::sum);
* }</pre>
- * though the map-reduce form is more readable and generally preferable. The generalized form
- * is provided for cases where significant work can be optimized away by combining mapping and
- * reducing into a single function.
+ * though the explicit map-reduce form is more readable and therefore should
+ * usually be preferred. The generalized form is provided for cases where
+ * significant work can be optimized away by combining mapping and reducing
+ * into a single function.
*
- * <p>More formally, the {@code identity} value must be an <em>identity</em> for the combiner
- * function. This means that for all {@code u}, {@code combiner.apply(identity, u)} is equal
- * to {@code u}. Additionally, the {@code combiner} function must be
- * <a href="#Associativity">associative</a> and must be compatible with the {@code accumulator}
- * function; for all {@code u} and {@code t}, the following must hold:
- * <pre>{@code
- * combiner.apply(u, accumulator.apply(identity, t)) == accumulator.apply(u, t)
- * }</pre>
+ * <h3><a name="MutableReduction">Mutable reduction</a></h3>
*
- * <h3><a name="MutableReduction">Mutable Reduction</a></h3>
- *
- * A <em>mutable</em> reduction operation is similar to an ordinary reduction, in that it reduces
- * a stream of values to a single value, but instead of producing a distinct single-valued result, it
- * mutates a general <em>result container</em>, such as a {@code Collection} or {@code StringBuilder},
+ * A <em>mutable reduction operation</em> accumulates input elements into a
+ * mutable result container, such as a {@code Collection} or {@code StringBuilder},
* as it processes the elements in the stream.
*
- * <p>For example, if we wanted to take a stream of strings and concatenate them into a single
- * long string, we <em>could</em> achieve this with ordinary reduction:
+ * <p>If we wanted to take a stream of strings and concatenate them into a
+ * single long string, we <em>could</em> achieve this with ordinary reduction:
* <pre>{@code
* String concatenated = strings.reduce("", String::concat)
* }</pre>
*
- * We would get the desired result, and it would even work in parallel. However, we might not
- * be happy about the performance! Such an implementation would do a great deal of string
- * copying, and the run time would be <em>O(n^2)</em> in the number of elements. A more
- * performant approach would be to accumulate the results into a {@link java.lang.StringBuilder}, which
- * is a mutable container for accumulating strings. We can use the same technique to
+ * <p>We would get the desired result, and it would even work in parallel. However,
+ * we might not be happy about the performance! Such an implementation would do
+ * a great deal of string copying, and the run time would be <em>O(n^2)</em> in
+ * the number of characters. A more performant approach would be to accumulate
+ * the results into a {@link java.lang.StringBuilder}, which is a mutable
+ * container for accumulating strings. We can use the same technique to
* parallelize mutable reduction as we do with ordinary reduction.
*
- * <p>The mutable reduction operation is called {@link java.util.stream.Stream#collect(Collector) collect()}, as it
- * collects together the desired results into a result container such as {@code StringBuilder}.
- * A {@code collect} operation requires three things: a factory function which will construct
- * new instances of the result container, an accumulating function that will update a result
- * container by incorporating a new element, and a combining function that can take two
- * result containers and merge their contents. The form of this is very similar to the general
+ * <p>The mutable reduction operation is called
+ * {@link java.util.stream.Stream#collect(Collector) collect()},
+ * as it collects together the desired results into a result container such
+ * as a {@code Collection}.
+ * A {@code collect} operation requires three functions:
+ * a factory function to construct new instances of the result container, an
+ * accumulator function to incorporate an input element into a result
+ * container, and a combining function to merge the contents of one result
+ * container into another. The form of this is very similar to the general
* form of ordinary reduction:
* <pre>{@code
* <R> R collect(Supplier<R> resultFactory,
* BiConsumer<R, ? super T> accumulator,
* BiConsumer<R, R> combiner);
* }</pre>
- * As with {@code reduce()}, the benefit of expressing {@code collect} in this abstract way is
- * that it is directly amenable to parallelization: we can accumulate partial results in parallel
- * and then combine them. For example, to collect the String representations of the elements
- * in a stream into an {@code ArrayList}, we could write the obvious sequential for-each form:
+ * <p>As with {@code reduce()}, a benefit of expressing {@code collect} in this
+ * abstract way is that it is directly amenable to parallelization: we can
+ * accumulate partial results in parallel and then combine them, so long as the
+ * accumulation and combining functions satisfy the appropriate requirements.
+ * For example, to collect the String representations of the elements in a
+ * stream into an {@code ArrayList}, we could write the obvious sequential
+ * for-each form:
* <pre>{@code
* ArrayList<String> strings = new ArrayList<>();
* for (T element : stream) {
@@ -377,92 +514,107 @@
* (c, e) -> c.add(e.toString()),
* (c1, c2) -> c1.addAll(c2));
* }</pre>
- * or, noting that we have buried a mapping operation inside the accumulator function, more
- * succinctly as:
- * <pre>{@code
- * ArrayList<String> strings = stream.map(Object::toString)
- * .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
- * }</pre>
- * Here, our supplier is just the {@link java.util.ArrayList#ArrayList() ArrayList constructor}, the
- * accumulator adds the stringified element to an {@code ArrayList}, and the combiner simply
- * uses {@link java.util.ArrayList#addAll addAll} to copy the strings from one container into the other.
- *
- * <p>As with the regular reduction operation, the ability to parallelize only comes if an
- * <a href="package-summary.html#Associativity">associativity</a> condition is met. The {@code combiner} is associative
- * if for result containers {@code r1}, {@code r2}, and {@code r3}:
- * <pre>{@code
- * combiner.accept(r1, r2);
- * combiner.accept(r1, r3);
- * }</pre>
- * is equivalent to
- * <pre>{@code
- * combiner.accept(r2, r3);
- * combiner.accept(r1, r2);
- * }</pre>
- * where equivalence means that {@code r1} is left in the same state (according to the meaning
- * of {@link java.lang.Object#equals equals} for the element types). Similarly, the {@code resultFactory}
- * must act as an <em>identity</em> with respect to the {@code combiner} so that for any result
- * container {@code r}:
+ * or, pulling the mapping operation out of the accumulator function, we could
+ * express it more succinctly as:
* <pre>{@code
- * combiner.accept(r, resultFactory.get());
+ * List<String> strings = stream.map(Object::toString)
+ * .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
* }</pre>
- * does not modify the state of {@code r} (again according to the meaning of
- * {@link java.lang.Object#equals equals}). Finally, the {@code accumulator} and {@code combiner} must be
- * compatible such that for a result container {@code r} and element {@code t}:
- * <pre>{@code
- * r2 = resultFactory.get();
- * accumulator.accept(r2, t);
- * combiner.accept(r, r2);
- * }</pre>
- * is equivalent to:
+ * Here, our supplier is just the {@link java.util.ArrayList#ArrayList()
+ * ArrayList constructor}, the accumulator adds the stringified element to an
+ * {@code ArrayList}, and the combiner simply uses {@link java.util.ArrayList#addAll addAll}
+ * to copy the strings from one container into the other.
+ *
+ * <p> The three aspects of {@code collect} -- supplier, accumulator, and combiner --
+ * are tightly coupled. We can use the abstraction of
+ * of a {@link java.util.stream.Collector} to capture all three aspects.
+ * The above example for collecting strings into a {@code List} can be rewritten
+ * using a standard {@code Collector} as:
* <pre>{@code
- * accumulator.accept(r,t);
- * }</pre>
- * where equivalence means that {@code r} is left in the same state (again according to the
- * meaning of {@link java.lang.Object#equals equals}).
- *
- * <p> The three aspects of {@code collect}: supplier, accumulator, and combiner, are often very
- * tightly coupled, and it is convenient to introduce the notion of a {@link java.util.stream.Collector} as
- * being an object that embodies all three aspects. There is a {@link java.util.stream.Stream#collect(Collector) collect}
- * method that simply takes a {@code Collector} and returns the resulting container.
- * The above example for collecting strings into a {@code List} can be rewritten using a
- * standard {@code Collector} as:
- * <pre>{@code
- * ArrayList<String> strings = stream.map(Object::toString)
- * .collect(Collectors.toList());
+ * List<String> strings = stream.map(Object::toString)
+ * .collect(Collectors.toList());
* }</pre>
*
- * <h3><a name="ConcurrentReduction">Reduction, Concurrency, and Ordering</a></h3>
+ * <p>Packaging mutable reductions into a Collector has another advantage:
+ * composability. The class {@link java.util.stream.Collectors} contains a
+ * number of predefined factories for collectors, including combinators
+ * that transform one collector into another. For example, suppose we have a
+ * collector that computes the sum of the salaries of a stream of
+ * employees, as follows:
+ *
+ * <pre>{@code
+ * Collector<Employee, ?, Integer> summingSalaries
+ * = Collectors.summingInt(Employee::getSalary);
+ * } </pre>
+ *
+ * (The {@code ?} for the second type parameter merely indicates that we don't
+ * care about the intermediate representation used by this collector.)
+ * If we wanted to create a collector to tabulate the sum of salaries by
+ * department, we could reuse {@code summingSalaries} using
+ * {@link java.util.stream.Collectors#groupingBy(java.util.function.Function, java.util.stream.Collector) groupingBy}:
+ *
+ * <pre>{@code
+ * Map<Department, Integer> salariesByDept
+ * = employees.stream().collect(Collectors.groupingBy(Employee::getDepartment,
+ * summingSalaries));
+ * } </pre>
*
- * With some complex reduction operations, for example a collect that produces a
- * {@code Map}, such as:
+ * <p>As with the regular reduction operation, {@code collect()} operations can
+ * only be parallelized if appropriate conditions are met. For any partially accumulated result,
+ * combining it with an empty result container must produce an equivalent
+ * result. That is, for a partially accumulated result {@code p} that is the
+ * result of any series of accumulator and combiner invocations, {@code p} must
+ * be equivalent to {@code combiner.apply(p, supplier.get())}.
+ *
+ * <p>Further, however the computation is split, it must produce an equivalent
+ * result. For any input elements {@code t1} and {@code t2}, the results
+ * {@code r1} and {@code r2} in the computation below must be equivalent:
+ * <pre>{@code
+ * A a1 = supplier.get();
+ * accumulator.accept(a1, t1);
+ * accumulator.accept(a1, t2);
+ * R r1 = finisher.apply(a1); // result without splitting
+ *
+ * A a2 = supplier.get();
+ * accumulator.accept(a2, t1);
+ * A a3 = supplier.get();
+ * accumulator.accept(a3, t2);
+ * R r2 = finisher.apply(combiner.apply(a2, a3)); // result with splitting
+ * } </pre>
+ *
+ * <p>Here, equivalence generally means according to {@link java.lang.Object#equals(Object)}.
+ * but in some cases equivalence may be relaxed to account for differences in
+ * order.
+ *
+ * <h3><a name="ConcurrentReduction">Reduction, concurrency, and ordering</a></h3>
+ *
+ * With some complex reduction operations, for example a {@code collect()} that
+ * produces a {@code Map}, such as:
* <pre>{@code
* Map<Buyer, List<Transaction>> salesByBuyer
* = txns.parallelStream()
* .collect(Collectors.groupingBy(Transaction::getBuyer));
* }</pre>
- * (where {@link java.util.stream.Collectors#groupingBy} is a utility function
- * that returns a {@link java.util.stream.Collector} for grouping sets of elements based on some key)
* it may actually be counterproductive to perform the operation in parallel.
* This is because the combining step (merging one {@code Map} into another by key)
* can be expensive for some {@code Map} implementations.
*
* <p>Suppose, however, that the result container used in this reduction
* was a concurrently modifiable collection -- such as a
- * {@link java.util.concurrent.ConcurrentHashMap ConcurrentHashMap}. In that case,
- * the parallel invocations of the accumulator could actually deposit their results
- * concurrently into the same shared result container, eliminating the need for the combiner to
- * merge distinct result containers. This potentially provides a boost
- * to the parallel execution performance. We call this a <em>concurrent</em> reduction.
+ * {@link java.util.concurrent.ConcurrentHashMap}. In that case, the parallel
+ * invocations of the accumulator could actually deposit their results
+ * concurrently into the same shared result container, eliminating the need for
+ * the combiner to merge distinct result containers. This potentially provides
+ * a boost to the parallel execution performance. We call this a <em>concurrent</em>
+ * reduction.
*
- * <p>A {@link java.util.stream.Collector} that supports concurrent reduction is marked with the
- * {@link java.util.stream.Collector.Characteristics#CONCURRENT} characteristic.
- * Having a concurrent collector is a necessary condition for performing a
- * concurrent reduction, but that alone is not sufficient. If you imagine multiple
- * accumulators depositing results into a shared container, the order in which
- * results are deposited is non-deterministic. Consequently, a concurrent reduction
- * is only possible if ordering is not important for the stream being processed.
- * The {@link java.util.stream.Stream#collect(Collector)}
+ * <p>A {@link java.util.stream.Collector} that supports concurrent reduction is
+ * marked with the {@link java.util.stream.Collector.Characteristics#CONCURRENT}
+ * characteristic. However, a concurrent collection also has a downside. If
+ * multiple threads are depositing results concurrently into a shared container,
+ * the order in which results are deposited is non-deterministic. Consequently,
+ * a concurrent reduction is only possible if ordering is not important for the
+ * stream being processed. The {@link java.util.stream.Stream#collect(Collector)}
* implementation will only perform a concurrent reduction if
* <ul>
* <li>The stream is parallel;</li>
@@ -472,15 +624,16 @@
* <li>Either the stream is unordered, or the collector has the
* {@link java.util.stream.Collector.Characteristics#UNORDERED} characteristic.
* </ul>
- * For example:
+ * You can ensure the stream is unordered by using the
+ * {@link java.util.stream.BaseStream#unordered()} method. For example:
* <pre>{@code
* Map<Buyer, List<Transaction>> salesByBuyer
* = txns.parallelStream()
* .unordered()
* .collect(groupingByConcurrent(Transaction::getBuyer));
* }</pre>
- * (where {@link java.util.stream.Collectors#groupingByConcurrent} is the concurrent companion
- * to {@code groupingBy}).
+ * (where {@link java.util.stream.Collectors#groupingByConcurrent} is the
+ * concurrent equivalent of {@code groupingBy}).
*
* <p>Note that if it is important that the elements for a given key appear in the
* order they appear in the source, then we cannot use a concurrent reduction,
@@ -488,79 +641,77 @@
* be constrained to implement either a sequential reduction or a merge-based
* parallel reduction.
*
- * <h2><a name="Associativity">Associativity</a></h2>
+ * <h3><a name="Associativity">Associativity</a></h3>
*
- * An operator or function {@code op} is <em>associative</em> if the following holds:
+ * An operator or function {@code op} is <em>associative</em> if the following
+ * holds:
* <pre>{@code
* (a op b) op c == a op (b op c)
* }</pre>
- * The importance of this to parallel evaluation can be seen if we expand this to four terms:
+ * The importance of this to parallel evaluation can be seen if we expand this
+ * to four terms:
* <pre>{@code
* a op b op c op d == (a op b) op (c op d)
* }</pre>
- * So we can evaluate {@code (a op b)} in parallel with {@code (c op d)} and then invoke {@code op} on
- * the results.
- * TODO what does associative mean for mutative combining functions?
- * FIXME: we described mutative associativity above.
+ * So we can evaluate {@code (a op b)} in parallel with {@code (c op d)}, and
+ * then invoke {@code op} on the results.
*
- * <h2><a name="StreamSources">Stream sources</a></h2>
- * TODO where does this section go?
+ * <p>Examples of associative operations include numeric addition, min, and max,
+ * and string concatenation.
+ *
+ * <h2><a name="StreamSources">Low-level stream construction</a></h2>
*
- * XXX - change to section to stream construction gradually introducing more
- * complex ways to construct
- * - construction from Collection
- * - construction from Iterator
- * - construction from array
- * - construction from generators
- * - construction from spliterator
+ * So far, all the stream examples have used methods like
+ * {@link java.util.Collection#stream()} or {@link java.util.Arrays#stream(Object[])}
+ * to obtain a stream. How are those stream-bearing methods implemented?
+ *
+ * <p>The class {@link java.util.stream.StreamSupport} has a number of low-level
+ * methods for creating a stream, all using some form of a {@link java.util.Spliterator}.
+ * A spliterator is the parallel analogue of an {@link java.util.Iterator}; it
+ * describes a (possibly infinite) collection of elements, with support for
+ * sequentially advancing, bulk traversal, and splitting off some portion of the
+ * input into another spliterator which can be processed in parallel. At the
+ * lowest level, all streams are driven by a spliterator.
*
- * XXX - the following is quite low-level but important aspect of stream constriction
- *
- * <p>A pipeline is initially constructed from a spliterator (see {@link java.util.Spliterator}) supplied by a stream source.
- * The spliterator covers elements of the source and provides element traversal operations
- * for a possibly-parallel computation. See methods on {@link java.util.stream.Streams} for construction
- * of pipelines using spliterators.
+ * <p>There are a number of implementation choices in implementing a spliterator,
+ * nearly all of which are tradeoffs between simplicity of implementation and
+ * runtime performance of streams using that spliterator. The simplest, but
+ * least performant, way to create a spliterator is to create one from an iterator
+ * using {@link java.util.Spliterators#spliteratorUnknownSize(java.util.Iterator, int)}.
+ * While such a spliterator will work, it will likely offer poor parallel
+ * performance, since we have lost sizing information (how big is the underlying
+ * data set), as well as being constrained to a simplistic splitting algorithm.
*
- * <p>A source may directly supply a spliterator. If so, the spliterator is traversed, split, or queried
- * for estimated size after, and never before, the terminal operation commences. It is strongly recommended
- * that the spliterator report a characteristic of {@code IMMUTABLE} or {@code CONCURRENT}, or be
- * <em>late-binding</em> and not bind to the elements it covers until traversed, split or queried for
- * estimated size.
+ * <p>A higher-quality spliterator will provide balanced and known-size splits,
+ * accurate sizing information, and a number of other
+ * {@link java.util.Spliterator#characteristics() characteristics} of the
+ * spliterator or data that can be used by implementations to optimize
+ * execution.
*
- * <p>If a source cannot directly supply a recommended spliterator then it may indirectly supply a spliterator
- * using a {@code Supplier}. The spliterator is obtained from the supplier after, and never before, the terminal
+ * <p>Spliterators for mutable data sources have an additional challenge; timing
+ * of binding to the data, since the data could change between the time the
+ * spliterator is created and the time the stream pipeline is executed. Ideally,
+ * a spliterator for a stream would report a characteristic of {@code IMMUTABLE}
+ * or {@code CONCURRENT}; if not it should be <a href="../Spliterator.html#binding"><em>late-binding</em></a>.
+ * If a source cannot directly supply a recommended spliterator, it may
+ * indirectly supply a spliterator using a {@code Supplier}, and construct a
+ * stream via the {@code Supplier}-accepting versions of
+ * {@link java.util.stream.StreamSupport#stream(Supplier, int, boolean) stream()}.
+ * The spliterator is obtained from the supplier only after the terminal
* operation of the stream pipeline commences.
*
- * <p>Such requirements significantly reduce the scope of potential interference to the interval starting
- * with the commencing of the terminal operation and ending with the producing a result or side-effect. See
- * <a href="package-summary.html#Non-Interference">Non-Interference</a> for
- * more details.
- *
- * XXX - move the following to the non-interference section
- *
- * <p>A source can be modified before the terminal operation commences and those modifications will be reflected in
- * the covered elements. Afterwards, and depending on the properties of the source, further modifications
- * might not be reflected and the throwing of a {@code ConcurrentModificationException} may occur.
+ * <p>These requirements significantly reduce the scope of potential interference
+ * between mutations of the stream source and execution of stream pipelines.
+ * Streams based on spliterators with the desired characteristics, or those using
+ * the Supplier-based factory forms, are immune to modifications of the data
+ * source prior to commencement of the terminal operation (provided the behavioral
+ * parameters to the stream operations meet the required criteria for non-interference
+ * and statelessness). See <a href="package-summary.html#Non-Interference">Non-Interference</a>
+ * for more details.
*
- * <p>For example, consider the following code:
- * <pre>{@code
- * List<String> l = new ArrayList(Arrays.asList("one", "two"));
- * Stream<String> sl = l.stream();
- * l.add("three");
- * String s = sl.collect(joining(" "));
- * }</pre>
- * First a list is created consisting of two strings: "one"; and "two". Then a stream is created from that list.
- * Next the list is modified by 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". However, if the list is modified after the terminal operation
- * commences, as in:
- * <pre>{@code
- * List<String> l = new ArrayList(Arrays.asList("one", "two"));
- * Stream<String> sl = l.stream();
- * String s = sl.peek(s -> l.add("BAD LAMBDA")).collect(joining(" "));
- * }</pre>
- * then a {@code ConcurrentModificationException} will be thrown since the {@code peek} operation will attempt
- * to add the string "BAD LAMBDA" to the list after the terminal operation has commenced.
+ * @since 1.8
*/
+package java.util.stream;
-package java.util.stream;
+import java.util.function.BinaryOperator;
+import java.util.function.UnaryOperator;