提交 f884bcee 编写于 作者: H henryjen

8025909: Lambda Library Spec Updates

8024179: Document limitations and performance characteristics of stream sources and operations
8024138: (Spec clarification) Lambda Metafacory spec should state DMH constraint on implMethod
Reviewed-by: mduigou
Contributed-by: brian.goetz@oracle.com, paul.sandoz@oracle.com
上级 0cfffffa
...@@ -51,10 +51,12 @@ public interface Iterable<T> { ...@@ -51,10 +51,12 @@ public interface Iterable<T> {
Iterator<T> iterator(); Iterator<T> iterator();
/** /**
* Performs the given action on the contents of the {@code Iterable}, in the * Performs the given action for each element of the {@code Iterable}
* order elements occur when iterating, until all elements have been * until all elements have been processed or the action throws an
* processed or the action throws an exception. Errors or runtime * exception. Unless otherwise specified by the implementing class,
* exceptions thrown by the action are relayed to the caller. * actions are performed in the order of iteration (if an iteration order
* is specified). Exceptions thrown by the action are relayed to the
* caller.
* *
* @implSpec * @implSpec
* <p>The default implementation behaves as if: * <p>The default implementation behaves as if:
......
...@@ -183,15 +183,15 @@ public class LambdaMetafactory { ...@@ -183,15 +183,15 @@ public class LambdaMetafactory {
* @param samMethodType MethodType of the method in the functional interface * @param samMethodType MethodType of the method in the functional interface
* to which the lambda or method reference is being * to which the lambda or method reference is being
* converted, represented as a MethodType. * converted, represented as a MethodType.
* @param implMethod The implementation method which should be called * @param implMethod A direct method handle describing the implementation
* (with suitable adaptation of argument types, return * method which should be called (with suitable adaptation
* types, and adjustment for captured arguments) when * of argument types, return types, and adjustment for
* methods of the resulting functional interface instance * captured arguments) when methods of the resulting
* are invoked. * functional interface instance are invoked.
* @param instantiatedMethodType The signature of the primary functional * @param instantiatedMethodType The signature of the primary functional
* interface method after type variables * interface method after type variables
* are substituted with their instantiation * are substituted with their instantiation
* from the capture site * from the capture site.
* @return a CallSite, which, when invoked, will return an instance of the * @return a CallSite, which, when invoked, will return an instance of the
* functional interface * functional interface
* @throws ReflectiveOperationException if the caller is not able to * @throws ReflectiveOperationException if the caller is not able to
...@@ -220,15 +220,21 @@ public class LambdaMetafactory { ...@@ -220,15 +220,21 @@ public class LambdaMetafactory {
* references to functional interfaces, which supports serialization and * references to functional interfaces, which supports serialization and
* other uncommon options. * other uncommon options.
* *
* The declared argument list for this method is: * <p>The declared argument list for this method is:
* *
* <pre>{@code
* CallSite altMetafactory(MethodHandles.Lookup caller, * CallSite altMetafactory(MethodHandles.Lookup caller,
* String invokedName, * String invokedName,
* MethodType invokedType, * MethodType invokedType,
* Object... args) * Object... args)
* }</pre>
* *
* but it behaves as if the argument list is: * <p>but it behaves as if the argument list is as follows, where names that
* appear in the argument list for
* {@link #metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)}
* have the same specification as in that method:
* *
* <pre>{@code
* CallSite altMetafactory(MethodHandles.Lookup caller, * CallSite altMetafactory(MethodHandles.Lookup caller,
* String invokedName, * String invokedName,
* MethodType invokedType, * MethodType invokedType,
...@@ -241,7 +247,15 @@ public class LambdaMetafactory { ...@@ -241,7 +247,15 @@ public class LambdaMetafactory {
* int bridgeCount, // IF flags has BRIDGES set * int bridgeCount, // IF flags has BRIDGES set
* MethodType... bridges // IF flags has BRIDGES set * MethodType... bridges // IF flags has BRIDGES set
* ) * )
* }</pre>
* *
* <p>If the flags contains {@code FLAG_SERIALIZABLE}, or one of the marker
* interfaces extends {@link Serializable}, the metafactory will link the
* call site to one that produces a serializable lambda. In addition to
* the lambda instance implementing {@code Serializable}, it will have a
* {@code writeReplace} method that returns an appropriate {@link
* SerializedLambda}, and an appropriate {@code $deserializeLambda$}
* method.
* *
* @param caller Stacked automatically by VM; represents a lookup context * @param caller Stacked automatically by VM; represents a lookup context
* with the accessibility privileges of the caller. * with the accessibility privileges of the caller.
...@@ -257,7 +271,7 @@ public class LambdaMetafactory { ...@@ -257,7 +271,7 @@ public class LambdaMetafactory {
* In the event that the implementation method is an * In the event that the implementation method is an
* instance method, the first argument in the invocation * instance method, the first argument in the invocation
* signature will correspond to the receiver. * signature will correspond to the receiver.
* @param args flags and optional arguments, as described above * @param args flags and optional arguments, as described above.
* @return a CallSite, which, when invoked, will return an instance of the * @return a CallSite, which, when invoked, will return an instance of the
* functional interface * functional interface
* @throws ReflectiveOperationException if the caller is not able to * @throws ReflectiveOperationException if the caller is not able to
......
...@@ -32,9 +32,26 @@ import java.security.PrivilegedExceptionAction; ...@@ -32,9 +32,26 @@ import java.security.PrivilegedExceptionAction;
import java.util.Objects; import java.util.Objects;
/** /**
* Serialized form of a lambda expression. The properties of this class represent the information that is present * Serialized form of a lambda expression. The properties of this class
* at the lambda factory site, including the identity of the primary functional interface method, the identity of the * represent the information that is present at the lambda factory site, including
* implementation method, and any variables captured from the local environment at the time of lambda capture. * static metafactory arguments such as the identity of the primary functional
* interface method and the identity of the implementation method, as well as
* dynamic metafactory arguments such as values captured from the lexical scope
* at the time of lambda capture.
*
* <p>Implementors of serializable lambdas, such as compilers or language
* runtime libraries, are expected to ensure that instances deserialize properly.
* One means to do so is to ensure that the {@code writeReplace} method returns
* an instance of {@code SerializedLambda}, rather than allowing default
* serialization to proceed.
*
* <p>{@code SerializedLambda} has a {@code readResolve} method that looks for
* a (possibly private) static method called
* {@code $deserializeLambda$(SerializedLambda)} in the capturing class, invokes
* that with itself as the first argument, and returns the result. Lambda classes
* implementing {@code $deserializeLambda$} are responsible for validating
* that the properties of the {@code SerializedLambda} are consistent with a
* lambda actually captured by that class.
* *
* @see LambdaMetafactory * @see LambdaMetafactory
*/ */
......
...@@ -127,7 +127,7 @@ public class DoubleSummaryStatistics implements DoubleConsumer { ...@@ -127,7 +127,7 @@ public class DoubleSummaryStatistics implements DoubleConsumer {
* numerical sum compared to a simple summation of {@code double} * numerical sum compared to a simple summation of {@code double}
* values. * values.
* *
* @apiNote Sorting values by increasing absolute magnitude tends to yield * @apiNote Values sorted by increasing absolute magnitude tend to yield
* more accurate results. * more accurate results.
* *
* @return the sum of values, or zero if none * @return the sum of values, or zero if none
......
...@@ -94,10 +94,10 @@ public interface Iterator<E> { ...@@ -94,10 +94,10 @@ public interface Iterator<E> {
} }
/** /**
* Performs the given action for each remaining element, in the order * Performs the given action for each remaining element until all elements
* elements occur when iterating, until all elements have been processed or * have been processed or the action throws an exception. Actions are
* the action throws an exception. Errors or runtime exceptions thrown by * performed in the order of iteration, if that order is specified.
* the action are relayed to the caller. * Exceptions thrown by the action are relayed to the caller.
* *
* @implSpec * @implSpec
* <p>The default implementation behaves as if: * <p>The default implementation behaves as if:
......
...@@ -192,8 +192,9 @@ public interface List<E> extends Collection<E> { ...@@ -192,8 +192,9 @@ public interface List<E> extends Collection<E> {
* The following code can be used to dump the list into a newly * The following code can be used to dump the list into a newly
* allocated array of <tt>String</tt>: * allocated array of <tt>String</tt>:
* *
* <pre> * <pre>{@code
* String[] y = x.toArray(new String[0]);</pre> * String[] y = x.toArray(new String[0]);
* }</pre>
* *
* Note that <tt>toArray(new Object[0])</tt> is identical in function to * Note that <tt>toArray(new Object[0])</tt> is identical in function to
* <tt>toArray()</tt>. * <tt>toArray()</tt>.
...@@ -383,14 +384,13 @@ public interface List<E> extends Collection<E> { ...@@ -383,14 +384,13 @@ public interface List<E> extends Collection<E> {
* *
* @implSpec * @implSpec
* The default implementation is equivalent to, for this {@code list}: * The default implementation is equivalent to, for this {@code list}:
* <pre> * <pre>{@code
* {@code * final ListIterator<E> li = list.listIterator();
* final ListIterator<E> li = list.listIterator(); * while (li.hasNext()) {
* while (li.hasNext()) { * li.set(operator.apply(li.next()));
* li.set(operator.apply(li.next())); * }
* } * }</pre>
* } *
* </pre>
* If the list's list-iterator does not support the {@code set} operation * If the list's list-iterator does not support the {@code set} operation
* then an {@code UnsupportedOperationException} will be thrown when * then an {@code UnsupportedOperationException} will be thrown when
* replacing the first element. * replacing the first element.
...@@ -469,11 +469,11 @@ public interface List<E> extends Collection<E> { ...@@ -469,11 +469,11 @@ public interface List<E> extends Collection<E> {
/** /**
* Returns the hash code value for this list. The hash code of a list * Returns the hash code value for this list. The hash code of a list
* is defined to be the result of the following calculation: * is defined to be the result of the following calculation:
* <pre> * <pre>{@code
* int hashCode = 1; * int hashCode = 1;
* for (E e : list) * for (E e : list)
* hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); * hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
* </pre> * }</pre>
* This ensures that <tt>list1.equals(list2)</tt> implies that * This ensures that <tt>list1.equals(list2)</tt> implies that
* <tt>list1.hashCode()==list2.hashCode()</tt> for any two lists, * <tt>list1.hashCode()==list2.hashCode()</tt> for any two lists,
* <tt>list1</tt> and <tt>list2</tt>, as required by the general * <tt>list1</tt> and <tt>list2</tt>, as required by the general
...@@ -640,9 +640,9 @@ public interface List<E> extends Collection<E> { ...@@ -640,9 +640,9 @@ public interface List<E> extends Collection<E> {
* a list can be used as a range operation by passing a subList view * a list can be used as a range operation by passing a subList view
* instead of a whole list. For example, the following idiom * instead of a whole list. For example, the following idiom
* removes a range of elements from a list: * removes a range of elements from a list:
* <pre> * <pre>{@code
* list.subList(from, to).clear(); * list.subList(from, to).clear();
* </pre> * }</pre>
* Similar idioms may be constructed for <tt>indexOf</tt> and * Similar idioms may be constructed for <tt>indexOf</tt> and
* <tt>lastIndexOf</tt>, and all of the algorithms in the * <tt>lastIndexOf</tt>, and all of the algorithms in the
* <tt>Collections</tt> class can be applied to a subList.<p> * <tt>Collections</tt> class can be applied to a subList.<p>
......
...@@ -562,9 +562,8 @@ public interface Map<K,V> { ...@@ -562,9 +562,8 @@ public interface Map<K,V> {
// Defaultable methods // Defaultable methods
/** /**
* Returns the value to which the specified key is mapped, * Returns the value to which the specified key is mapped, or
* or {@code defaultValue} if this map contains no mapping * {@code defaultValue} if this map contains no mapping for the key.
* for the key.
* *
* <p>The default implementation makes no guarantees about synchronization * <p>The default implementation makes no guarantees about synchronization
* or atomicity properties of this method. Any implementation providing * or atomicity properties of this method. Any implementation providing
...@@ -591,9 +590,10 @@ public interface Map<K,V> { ...@@ -591,9 +590,10 @@ public interface Map<K,V> {
} }
/** /**
* Performs the given action on each entry in this map, in the order entries * Performs the given action for each entry in this map until all entries
* are returned by an entry set iterator (which may be unspecified), until * have been processed or the action throws an exception. Unless
* all entries have been processed or the action throws an {@code Exception}. * otherwise specified by the implementing class, actions are performed in
* the order of entry set iteration (if an iteration order is specified.)
* Exceptions thrown by the action are relayed to the caller. * Exceptions thrown by the action are relayed to the caller.
* *
* <p>The default implementation should be overridden by implementations if * <p>The default implementation should be overridden by implementations if
...@@ -636,9 +636,9 @@ public interface Map<K,V> { ...@@ -636,9 +636,9 @@ public interface Map<K,V> {
/** /**
* Replaces each entry's value with the result of invoking the given * Replaces each entry's value with the result of invoking the given
* function on that entry, in the order entries are returned by an entry * function on that entry until all entries have been processed or the
* set iterator, until all entries have been processed or the function * function throws an exception. Exceptions thrown by the function are
* throws an exception. * relayed to the caller.
* *
* <p>The default implementation makes no guarantees about synchronization * <p>The default implementation makes no guarantees about synchronization
* or atomicity properties of this method. Any implementation providing * or atomicity properties of this method. Any implementation providing
......
...@@ -76,6 +76,7 @@ public interface PrimitiveIterator<T, T_CONS> extends Iterator<T> { ...@@ -76,6 +76,7 @@ public interface PrimitiveIterator<T, T_CONS> extends Iterator<T> {
* @param action The action to be performed for each element * @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null * @throws NullPointerException if the specified action is null
*/ */
@SuppressWarnings("overloads")
void forEachRemaining(T_CONS action); void forEachRemaining(T_CONS action);
/** /**
...@@ -93,10 +94,10 @@ public interface PrimitiveIterator<T, T_CONS> extends Iterator<T> { ...@@ -93,10 +94,10 @@ public interface PrimitiveIterator<T, T_CONS> extends Iterator<T> {
int nextInt(); int nextInt();
/** /**
* Performs the given action for each remaining element, in the order * Performs the given action for each remaining element until all elements
* elements occur when iterating, until all elements have been processed * have been processed or the action throws an exception. Actions are
* or the action throws an exception. Errors or runtime exceptions * performed in the order of iteration, if that order is specified.
* thrown by the action are relayed to the caller. * Exceptions thrown by the action are relayed to the caller.
* *
* @implSpec * @implSpec
* <p>The default implementation behaves as if: * <p>The default implementation behaves as if:
...@@ -167,10 +168,10 @@ public interface PrimitiveIterator<T, T_CONS> extends Iterator<T> { ...@@ -167,10 +168,10 @@ public interface PrimitiveIterator<T, T_CONS> extends Iterator<T> {
long nextLong(); long nextLong();
/** /**
* Performs the given action for each remaining element, in the order * Performs the given action for each remaining element until all elements
* elements occur when iterating, until all elements have been processed * have been processed or the action throws an exception. Actions are
* or the action throws an exception. Errors or runtime exceptions * performed in the order of iteration, if that order is specified.
* thrown by the action are relayed to the caller. * Exceptions thrown by the action are relayed to the caller.
* *
* @implSpec * @implSpec
* <p>The default implementation behaves as if: * <p>The default implementation behaves as if:
...@@ -240,10 +241,10 @@ public interface PrimitiveIterator<T, T_CONS> extends Iterator<T> { ...@@ -240,10 +241,10 @@ public interface PrimitiveIterator<T, T_CONS> extends Iterator<T> {
double nextDouble(); double nextDouble();
/** /**
* Performs the given action for each remaining element, in the order * Performs the given action for each remaining element until all elements
* elements occur when iterating, until all elements have been processed * have been processed or the action throws an exception. Actions are
* or the action throws an exception. Errors or runtime exceptions * performed in the order of iteration, if that order is specified.
* thrown by the action are relayed to the caller. * Exceptions thrown by the action are relayed to the caller.
* *
* @implSpec * @implSpec
* <p>The default implementation behaves as if: * <p>The default implementation behaves as if:
......
...@@ -613,6 +613,7 @@ public interface Spliterator<T> { ...@@ -613,6 +613,7 @@ public interface Spliterator<T> {
* upon entry to this method, else {@code true}. * upon entry to this method, else {@code true}.
* @throws NullPointerException if the specified action is null * @throws NullPointerException if the specified action is null
*/ */
@SuppressWarnings("overloads")
boolean tryAdvance(T_CONS action); boolean tryAdvance(T_CONS action);
/** /**
...@@ -630,6 +631,7 @@ public interface Spliterator<T> { ...@@ -630,6 +631,7 @@ public interface Spliterator<T> {
* @param action The action * @param action The action
* @throws NullPointerException if the specified action is null * @throws NullPointerException if the specified action is null
*/ */
@SuppressWarnings("overloads")
default void forEachRemaining(T_CONS action) { default void forEachRemaining(T_CONS action) {
do { } while (tryAdvance(action)); do { } while (tryAdvance(action));
} }
......
...@@ -60,7 +60,11 @@ ...@@ -60,7 +60,11 @@
* actions, or predicates. In documenting functional interfaces, or referring * actions, or predicates. In documenting functional interfaces, or referring
* to variables typed as functional interfaces, it is common to refer directly * to variables typed as functional interfaces, it is common to refer directly
* to those abstract concepts, for example using "this function" instead of * to those abstract concepts, for example using "this function" instead of
* "the function represented by this object". * "the function represented by this object". When an API method is said to
* accept or return a functional interface in this manner, such as "applies the
* provided function to...", this is understood to mean a <i>non-null</i>
* reference to an object implementing the appropriate functional interface,
* unless potential nullity is explicitly specified.
* *
* <p>The functional interfaces in this package follow an extensible naming * <p>The functional interfaces in this package follow an extensible naming
* convention, as follows: * convention, as follows:
......
...@@ -35,9 +35,10 @@ import java.util.function.IntConsumer; ...@@ -35,9 +35,10 @@ import java.util.function.IntConsumer;
import java.util.function.Predicate; import java.util.function.Predicate;
/** /**
* A sequence of elements supporting sequential and parallel aggregate * Base interface for streams, which are sequences of elements supporting
* operations. The following example illustrates an aggregate operation using * sequential and parallel aggregate operations. The following example
* {@link Stream} and {@link IntStream}: * illustrates an aggregate operation using the stream types {@link Stream}
* and {@link IntStream}, computing the sum of the weights of the red widgets:
* *
* <pre>{@code * <pre>{@code
* int sum = widgets.stream() * int sum = widgets.stream()
...@@ -46,80 +47,18 @@ import java.util.function.Predicate; ...@@ -46,80 +47,18 @@ import java.util.function.Predicate;
* .sum(); * .sum();
* }</pre> * }</pre>
* *
* In this example, {@code widgets} is a {@code Collection<Widget>}. We create * See the class documentation for {@link Stream} and the package documentation
* a stream of {@code Widget} objects via {@link Collection#stream Collection.stream()}, * for <a href="package-summary.html">java.util.stream</a> for additional
* filter it to produce a stream containing only the red widgets, and then * specification of streams, stream operations, stream pipelines, and
* transform it into a stream of {@code int} values representing the weight of * parallelism, which governs the behavior of all stream types.
* each red widget. Then this stream is summed to produce a total weight.
*
* <p>To perform a computation, stream
* <a href="package-summary.html#StreamOps">operations</a> are composed into a
* <em>stream pipeline</em>. A stream pipeline consists of a source (which
* might be an array, a collection, a generator function, an IO channel,
* etc), zero or more <em>intermediate operations</em> (which transform a
* stream into another stream, such as {@link Stream#filter(Predicate)}), and a
* <em>terminal operation</em> (which produces a result or side-effect, such
* as {@link IntStream#sum()} or {@link IntStream#forEach(IntConsumer)}).
* Streams are lazy; computation on the source data is only performed when the
* terminal operation is initiated, and source elements are consumed only
* as needed.
*
* <p>Collections and streams, while bearing some superficial similarities,
* have different goals. Collections are primarily concerned with the efficient
* management of, and access to, their elements. By contrast, streams do not
* provide a means to directly access or manipulate their elements, and are
* instead concerned with declaratively describing their source and the
* computational operations which will be performed in aggregate on that source.
* However, if the provided stream operations do not offer the desired
* functionality, the {@link #iterator()} and {@link #spliterator()} operations
* can be used to perform a controlled traversal.
*
* <p>A stream pipeline, like the "widgets" example above, can be viewed as
* a <em>query</em> on the stream source. Unless the source was explicitly
* designed for concurrent modification (such as a {@link ConcurrentHashMap}),
* unpredictable or erroneous behavior may result from modifying the stream
* source while it is being queried.
*
* <p>Most stream operations accept parameters that describe user-specified
* behavior, such as the lambda expression {@code 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 <T> the type of the stream elements
* @param <S> the type of of the stream implementing {@code BaseStream} * @param <S> the type of of the stream implementing {@code BaseStream}
* @since 1.8 * @since 1.8
* @see Stream
* @see IntStream
* @see LongStream
* @see DoubleStream
* @see <a href="package-summary.html">java.util.stream</a> * @see <a href="package-summary.html">java.util.stream</a>
*/ */
public interface BaseStream<T, S extends BaseStream<T, S>> public interface BaseStream<T, S extends BaseStream<T, S>>
......
...@@ -462,7 +462,7 @@ public final class Collectors { ...@@ -462,7 +462,7 @@ public final class Collectors {
*/ */
public static <T> Collector<T, ?, Integer> public static <T> Collector<T, ?, Integer>
summingInt(ToIntFunction<? super T> mapper) { summingInt(ToIntFunction<? super T> mapper) {
return new CollectorImpl<T, int[], Integer>( return new CollectorImpl<>(
() -> new int[1], () -> new int[1],
(a, t) -> { a[0] += mapper.applyAsInt(t); }, (a, t) -> { a[0] += mapper.applyAsInt(t); },
(a, b) -> { a[0] += b[0]; return a; }, (a, b) -> { a[0] += b[0]; return a; },
...@@ -480,7 +480,7 @@ public final class Collectors { ...@@ -480,7 +480,7 @@ public final class Collectors {
*/ */
public static <T> Collector<T, ?, Long> public static <T> Collector<T, ?, Long>
summingLong(ToLongFunction<? super T> mapper) { summingLong(ToLongFunction<? super T> mapper) {
return new CollectorImpl<T, long[], Long>( return new CollectorImpl<>(
() -> new long[1], () -> new long[1],
(a, t) -> { a[0] += mapper.applyAsLong(t); }, (a, t) -> { a[0] += mapper.applyAsLong(t); },
(a, b) -> { a[0] += b[0]; return a; }, (a, b) -> { a[0] += b[0]; return a; },
...@@ -505,7 +505,7 @@ public final class Collectors { ...@@ -505,7 +505,7 @@ public final class Collectors {
*/ */
public static <T> Collector<T, ?, Double> public static <T> Collector<T, ?, Double>
summingDouble(ToDoubleFunction<? super T> mapper) { summingDouble(ToDoubleFunction<? super T> mapper) {
return new CollectorImpl<T, double[], Double>( return new CollectorImpl<>(
() -> new double[1], () -> new double[1],
(a, t) -> { a[0] += mapper.applyAsDouble(t); }, (a, t) -> { a[0] += mapper.applyAsDouble(t); },
(a, b) -> { a[0] += b[0]; return a; }, (a, b) -> { a[0] += b[0]; return a; },
...@@ -523,7 +523,7 @@ public final class Collectors { ...@@ -523,7 +523,7 @@ public final class Collectors {
*/ */
public static <T> Collector<T, ?, Double> public static <T> Collector<T, ?, Double>
averagingInt(ToIntFunction<? super T> mapper) { averagingInt(ToIntFunction<? super T> mapper) {
return new CollectorImpl<T, long[], Double>( return new CollectorImpl<>(
() -> new long[2], () -> new long[2],
(a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; }, (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; },
(a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
...@@ -541,7 +541,7 @@ public final class Collectors { ...@@ -541,7 +541,7 @@ public final class Collectors {
*/ */
public static <T> Collector<T, ?, Double> public static <T> Collector<T, ?, Double>
averagingLong(ToLongFunction<? super T> mapper) { averagingLong(ToLongFunction<? super T> mapper) {
return new CollectorImpl<T, long[], Double>( return new CollectorImpl<>(
() -> new long[2], () -> new long[2],
(a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; }, (a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; },
(a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
...@@ -566,7 +566,7 @@ public final class Collectors { ...@@ -566,7 +566,7 @@ public final class Collectors {
*/ */
public static <T> Collector<T, ?, Double> public static <T> Collector<T, ?, Double>
averagingDouble(ToDoubleFunction<? super T> mapper) { averagingDouble(ToDoubleFunction<? super T> mapper) {
return new CollectorImpl<T, double[], Double>( return new CollectorImpl<>(
() -> new double[2], () -> new double[2],
(a, t) -> { a[0] += mapper.applyAsDouble(t); a[1]++; }, (a, t) -> { a[0] += mapper.applyAsDouble(t); a[1]++; },
(a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
...@@ -723,6 +723,14 @@ public final class Collectors { ...@@ -723,6 +723,14 @@ public final class Collectors {
* groupingBy(classifier, toList()); * groupingBy(classifier, toList());
* }</pre> * }</pre>
* *
* @implNote
* The returned {@code Collector} is not concurrent. For parallel stream
* pipelines, the {@code combiner} function operates by merging the keys
* from one map into another, which can be an expensive operation. If
* preservation of the order in which elements appear in the resulting {@code Map}
* collector is not required, using {@link #groupingByConcurrent(Function)}
* may offer better parallel performance.
*
* @param <T> the type of the input elements * @param <T> the type of the input elements
* @param <K> the type of the keys * @param <K> the type of the keys
* @param classifier the classifier function mapping input elements to keys * @param classifier the classifier function mapping input elements to keys
...@@ -759,6 +767,14 @@ public final class Collectors { ...@@ -759,6 +767,14 @@ public final class Collectors {
* mapping(Person::getLastName, toSet()))); * mapping(Person::getLastName, toSet())));
* }</pre> * }</pre>
* *
* @implNote
* The returned {@code Collector} is not concurrent. For parallel stream
* pipelines, the {@code combiner} function operates by merging the keys
* from one map into another, which can be an expensive operation. If
* preservation of the order in which elements are presented to the downstream
* collector is not required, using {@link #groupingByConcurrent(Function, Collector)}
* may offer better parallel performance.
*
* @param <T> the type of the input elements * @param <T> the type of the input elements
* @param <K> the type of the keys * @param <K> the type of the keys
* @param <A> the intermediate accumulation type of the downstream collector * @param <A> the intermediate accumulation type of the downstream collector
...@@ -798,6 +814,14 @@ public final class Collectors { ...@@ -798,6 +814,14 @@ public final class Collectors {
* mapping(Person::getLastName, toSet()))); * mapping(Person::getLastName, toSet())));
* }</pre> * }</pre>
* *
* @implNote
* The returned {@code Collector} is not concurrent. For parallel stream
* pipelines, the {@code combiner} function operates by merging the keys
* from one map into another, which can be an expensive operation. If
* preservation of the order in which elements are presented to the downstream
* collector is not required, using {@link #groupingByConcurrent(Function, Supplier, Collector)}
* may offer better parallel performance.
*
* @param <T> the type of the input elements * @param <T> the type of the input elements
* @param <K> the type of the keys * @param <K> the type of the keys
* @param <A> the intermediate accumulation type of the downstream collector * @param <A> the intermediate accumulation type of the downstream collector
...@@ -871,7 +895,7 @@ public final class Collectors { ...@@ -871,7 +895,7 @@ public final class Collectors {
* @param <T> the type of the input elements * @param <T> the type of the input elements
* @param <K> the type of the keys * @param <K> the type of the keys
* @param classifier a classifier function mapping input elements to keys * @param classifier a classifier function mapping input elements to keys
* @return a {@code Collector} implementing the group-by operation * @return a concurrent, unordered {@code Collector} implementing the group-by operation
* *
* @see #groupingBy(Function) * @see #groupingBy(Function)
* @see #groupingByConcurrent(Function, Collector) * @see #groupingByConcurrent(Function, Collector)
...@@ -912,7 +936,7 @@ public final class Collectors { ...@@ -912,7 +936,7 @@ public final class Collectors {
* @param <D> the result type of the downstream reduction * @param <D> the result type of the downstream reduction
* @param classifier a classifier function mapping input elements to keys * @param classifier a classifier function mapping input elements to keys
* @param downstream a {@code Collector} implementing the downstream reduction * @param downstream a {@code Collector} implementing the downstream reduction
* @return a {@code Collector} implementing the cascaded group-by operation * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
* *
* @see #groupingBy(Function, Collector) * @see #groupingBy(Function, Collector)
* @see #groupingByConcurrent(Function) * @see #groupingByConcurrent(Function)
...@@ -958,7 +982,7 @@ public final class Collectors { ...@@ -958,7 +982,7 @@ public final class Collectors {
* @param downstream a {@code Collector} implementing the downstream reduction * @param downstream a {@code Collector} implementing the downstream reduction
* @param mapFactory a function which, when called, produces a new empty * @param mapFactory a function which, when called, produces a new empty
* {@code ConcurrentMap} of the desired type * {@code ConcurrentMap} of the desired type
* @return a {@code Collector} implementing the cascaded group-by operation * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
* *
* @see #groupingByConcurrent(Function) * @see #groupingByConcurrent(Function)
* @see #groupingByConcurrent(Function, Collector) * @see #groupingByConcurrent(Function, Collector)
...@@ -1072,7 +1096,7 @@ public final class Collectors { ...@@ -1072,7 +1096,7 @@ public final class Collectors {
} }
/** /**
* Returns a {@code Collector} that accumulate elements into a * Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided * {@code Map} whose keys and values are the result of applying the provided
* mapping functions to the input elements. * mapping functions to the input elements.
* *
...@@ -1101,6 +1125,14 @@ public final class Collectors { ...@@ -1101,6 +1125,14 @@ public final class Collectors {
* Functions.identity()); * Functions.identity());
* }</pre> * }</pre>
* *
* @implNote
* The returned {@code Collector} is not concurrent. For parallel stream
* pipelines, the {@code combiner} function operates by merging the keys
* from one map into another, which can be an expensive operation. If it is
* not required that results are inserted into the {@code Map} in encounter
* order, using {@link #toConcurrentMap(Function, Function)}
* may offer better parallel performance.
*
* @param <T> the type of the input elements * @param <T> the type of the input elements
* @param <K> the output type of the key mapping function * @param <K> the output type of the key mapping function
* @param <U> the output type of the value mapping function * @param <U> the output type of the value mapping function
...@@ -1121,7 +1153,7 @@ public final class Collectors { ...@@ -1121,7 +1153,7 @@ public final class Collectors {
} }
/** /**
* Returns a {@code Collector} that accumulate elements into a * Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided * {@code Map} whose keys and values are the result of applying the provided
* mapping functions to the input elements. * mapping functions to the input elements.
* *
...@@ -1146,6 +1178,14 @@ public final class Collectors { ...@@ -1146,6 +1178,14 @@ public final class Collectors {
* (s, a) -> s + ", " + a)); * (s, a) -> s + ", " + a));
* }</pre> * }</pre>
* *
* @implNote
* The returned {@code Collector} is not concurrent. For parallel stream
* pipelines, the {@code combiner} function operates by merging the keys
* from one map into another, which can be an expensive operation. If it is
* not required that results are merged into the {@code Map} in encounter
* order, using {@link #toConcurrentMap(Function, Function, BinaryOperator)}
* may offer better parallel performance.
*
* @param <T> the type of the input elements * @param <T> the type of the input elements
* @param <K> the output type of the key mapping function * @param <K> the output type of the key mapping function
* @param <U> the output type of the value mapping function * @param <U> the output type of the value mapping function
...@@ -1172,7 +1212,7 @@ public final class Collectors { ...@@ -1172,7 +1212,7 @@ public final class Collectors {
} }
/** /**
* Returns a {@code Collector} that accumulate elements into a * Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided * {@code Map} whose keys and values are the result of applying the provided
* mapping functions to the input elements. * mapping functions to the input elements.
* *
...@@ -1182,6 +1222,14 @@ public final class Collectors { ...@@ -1182,6 +1222,14 @@ public final class Collectors {
* results are merged using the provided merging function. The {@code Map} * results are merged using the provided merging function. The {@code Map}
* is created by a provided supplier function. * is created by a provided supplier function.
* *
* @implNote
* The returned {@code Collector} is not concurrent. For parallel stream
* pipelines, the {@code combiner} function operates by merging the keys
* from one map into another, which can be an expensive operation. If it is
* not required that results are merged into the {@code Map} in encounter
* order, using {@link #toConcurrentMap(Function, Function, BinaryOperator, Supplier)}
* may offer better parallel performance.
*
* @param <T> the type of the input elements * @param <T> the type of the input elements
* @param <K> the output type of the key mapping function * @param <K> the output type of the key mapping function
* @param <U> the output type of the value mapping function * @param <U> the output type of the value mapping function
...@@ -1215,7 +1263,7 @@ public final class Collectors { ...@@ -1215,7 +1263,7 @@ public final class Collectors {
} }
/** /**
* Returns a {@code Collector} that accumulate elements into a * Returns a concurrent {@code Collector} that accumulates elements into a
* {@code ConcurrentMap} whose keys and values are the result of applying * {@code ConcurrentMap} whose keys and values are the result of applying
* the provided mapping functions to the input elements. * the provided mapping functions to the input elements.
* *
...@@ -1252,7 +1300,7 @@ public final class Collectors { ...@@ -1252,7 +1300,7 @@ public final class Collectors {
* @param <U> the output type of the value mapping function * @param <U> the output type of the value mapping function
* @param keyMapper the mapping function to produce keys * @param keyMapper the mapping function to produce keys
* @param valueMapper the mapping function to produce values * @param valueMapper the mapping function to produce values
* @return a concurrent {@code Collector} which collects elements into a * @return a concurrent, unordered {@code Collector} which collects elements into a
* {@code ConcurrentMap} whose keys are the result of applying a key mapping * {@code ConcurrentMap} whose keys are the result of applying a key mapping
* function to the input elements, and whose values are the result of * function to the input elements, and whose values are the result of
* applying a value mapping function to the input elements * applying a value mapping function to the input elements
...@@ -1268,7 +1316,7 @@ public final class Collectors { ...@@ -1268,7 +1316,7 @@ public final class Collectors {
} }
/** /**
* Returns a {@code Collector} that accumulate elements into a * Returns a concurrent {@code Collector} that accumulates elements into a
* {@code ConcurrentMap} whose keys and values are the result of applying * {@code ConcurrentMap} whose keys and values are the result of applying
* the provided mapping functions to the input elements. * the provided mapping functions to the input elements.
* *
...@@ -1303,7 +1351,7 @@ public final class Collectors { ...@@ -1303,7 +1351,7 @@ public final class Collectors {
* @param mergeFunction a merge function, used to resolve collisions between * @param mergeFunction a merge function, used to resolve collisions between
* values associated with the same key, as supplied * values associated with the same key, as supplied
* to {@link Map#merge(Object, Object, BiFunction)} * to {@link Map#merge(Object, Object, BiFunction)}
* @return a concurrent {@code Collector} which collects elements into a * @return a concurrent, unordered {@code Collector} which collects elements into a
* {@code ConcurrentMap} whose keys are the result of applying a key mapping * {@code ConcurrentMap} whose keys are the result of applying a key mapping
* function to the input elements, and whose values are the result of * function to the input elements, and whose values are the result of
* applying a value mapping function to all input elements equal to the key * applying a value mapping function to all input elements equal to the key
...@@ -1322,7 +1370,7 @@ public final class Collectors { ...@@ -1322,7 +1370,7 @@ public final class Collectors {
} }
/** /**
* Returns a {@code Collector} that accumulate elements into a * Returns a concurrent {@code Collector} that accumulates elements into a
* {@code ConcurrentMap} whose keys and values are the result of applying * {@code ConcurrentMap} whose keys and values are the result of applying
* the provided mapping functions to the input elements. * the provided mapping functions to the input elements.
* *
...@@ -1345,7 +1393,7 @@ public final class Collectors { ...@@ -1345,7 +1393,7 @@ public final class Collectors {
* to {@link Map#merge(Object, Object, BiFunction)} * to {@link Map#merge(Object, Object, BiFunction)}
* @param mapSupplier a function which returns a new, empty {@code Map} into * @param mapSupplier a function which returns a new, empty {@code Map} into
* which the results will be inserted * which the results will be inserted
* @return a concurrent {@code Collector} which collects elements into a * @return a concurrent, unordered {@code Collector} which collects elements into a
* {@code ConcurrentMap} whose keys are the result of applying a key mapping * {@code ConcurrentMap} whose keys are the result of applying a key mapping
* function to the input elements, and whose values are the result of * function to the input elements, and whose values are the result of
* applying a value mapping function to all input elements equal to the key * applying a value mapping function to all input elements equal to the key
......
...@@ -51,9 +51,13 @@ import java.util.function.ObjLongConsumer; ...@@ -51,9 +51,13 @@ import java.util.function.ObjLongConsumer;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
* A sequence of elements supporting sequential and parallel aggregate * A sequence of primitive long-valued elements supporting sequential and parallel
* operations. The following example illustrates an aggregate operation using * aggregate operations. This is the {@code long} primitive specialization of
* {@link Stream} and {@link LongStream}: * {@link Stream}.
*
* <p>The following example illustrates an aggregate operation using
* {@link Stream} and {@link LongStream}, computing the sum of the weights of the
* red widgets:
* *
* <pre>{@code * <pre>{@code
* long sum = widgets.stream() * long sum = widgets.stream()
...@@ -62,78 +66,13 @@ import java.util.function.Supplier; ...@@ -62,78 +66,13 @@ import java.util.function.Supplier;
* .sum(); * .sum();
* }</pre> * }</pre>
* *
* In this example, {@code widgets} is a {@code Collection<Widget>}. We create * See the class documentation for {@link Stream} and the package documentation
* a stream of {@code Widget} objects via {@link Collection#stream Collection.stream()}, * for <a href="package-summary.html">java.util.stream</a> for additional
* filter it to produce a stream containing only the red widgets, and then * specification of streams, stream operations, stream pipelines, and
* transform it into a stream of {@code long} values representing the weight of * parallelism.
* 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 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>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>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.
* *
* @since 1.8 * @since 1.8
* @see Stream
* @see <a href="package-summary.html">java.util.stream</a> * @see <a href="package-summary.html">java.util.stream</a>
*/ */
public interface LongStream extends BaseStream<Long, LongStream> { public interface LongStream extends BaseStream<Long, LongStream> {
...@@ -145,9 +84,10 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -145,9 +84,10 @@ public interface LongStream extends BaseStream<Long, LongStream> {
* <p>This is an <a href="package-summary.html#StreamOps">intermediate * <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>. * operation</a>.
* *
* @param predicate a <a href="package-summary.html#NonInterference"> * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
* non-interfering, stateless</a> predicate to apply to * <a href="package-summary.html#Statelessness">stateless</a>
* each element to determine if it should be included * predicate to apply to each element to determine if it
* should be included
* @return the new stream * @return the new stream
*/ */
LongStream filter(LongPredicate predicate); LongStream filter(LongPredicate predicate);
...@@ -159,9 +99,9 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -159,9 +99,9 @@ public interface LongStream extends BaseStream<Long, LongStream> {
* <p>This is an <a href="package-summary.html#StreamOps">intermediate * <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>. * operation</a>.
* *
* @param mapper a <a href="package-summary.html#NonInterference"> * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
* non-interfering, stateless</a> function to apply to each * <a href="package-summary.html#Statelessness">stateless</a>
* element * function to apply to each element
* @return the new stream * @return the new stream
*/ */
LongStream map(LongUnaryOperator mapper); LongStream map(LongUnaryOperator mapper);
...@@ -174,9 +114,9 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -174,9 +114,9 @@ public interface LongStream extends BaseStream<Long, LongStream> {
* intermediate operation</a>. * intermediate operation</a>.
* *
* @param <U> the element type of the new stream * @param <U> the element type of the new stream
* @param mapper a <a href="package-summary.html#NonInterference"> * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
* non-interfering, stateless</a> function to apply to each * <a href="package-summary.html#Statelessness">stateless</a>
* element * function to apply to each element
* @return the new stream * @return the new stream
*/ */
<U> Stream<U> mapToObj(LongFunction<? extends U> mapper); <U> Stream<U> mapToObj(LongFunction<? extends U> mapper);
...@@ -188,9 +128,9 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -188,9 +128,9 @@ public interface LongStream extends BaseStream<Long, LongStream> {
* <p>This is an <a href="package-summary.html#StreamOps">intermediate * <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>. * operation</a>.
* *
* @param mapper a <a href="package-summary.html#NonInterference"> * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
* non-interfering, stateless</a> function to apply to each * <a href="package-summary.html#Statelessness">stateless</a>
* element * function to apply to each element
* @return the new stream * @return the new stream
*/ */
IntStream mapToInt(LongToIntFunction mapper); IntStream mapToInt(LongToIntFunction mapper);
...@@ -202,9 +142,9 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -202,9 +142,9 @@ public interface LongStream extends BaseStream<Long, LongStream> {
* <p>This is an <a href="package-summary.html#StreamOps">intermediate * <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>. * operation</a>.
* *
* @param mapper a <a href="package-summary.html#NonInterference"> * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
* non-interfering, stateless</a> function to apply to each * <a href="package-summary.html#Statelessness">stateless</a>
* element * function to apply to each element
* @return the new stream * @return the new stream
*/ */
DoubleStream mapToDouble(LongToDoubleFunction mapper); DoubleStream mapToDouble(LongToDoubleFunction mapper);
...@@ -219,10 +159,10 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -219,10 +159,10 @@ public interface LongStream extends BaseStream<Long, LongStream> {
* <p>This is an <a href="package-summary.html#StreamOps">intermediate * <p>This is an <a href="package-summary.html#StreamOps">intermediate
* operation</a>. * operation</a>.
* *
* @param mapper a <a href="package-summary.html#NonInterference"> * @param mapper a <a href="package-summary.html#NonInterference">non-interfering</a>,
* non-interfering, stateless</a> function to apply to * <a href="package-summary.html#Statelessness">stateless</a>
* each element which produces an {@code LongStream} of new * function to apply to each element which produces a
* values * {@code LongStream} of new values
* @return the new stream * @return the new stream
* @see Stream#flatMap(Function) * @see Stream#flatMap(Function)
*/ */
...@@ -421,9 +361,10 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -421,9 +361,10 @@ public interface LongStream extends BaseStream<Long, LongStream> {
* synchronization and with greatly reduced risk of data races. * synchronization and with greatly reduced risk of data races.
* *
* @param identity the identity value for the accumulating function * @param identity the identity value for the accumulating function
* @param op an <a href="package-summary.html#Associativity">associative</a> * @param op an <a href="package-summary.html#Associativity">associative</a>,
* <a href="package-summary.html#NonInterference">non-interfering, * <a href="package-summary.html#NonInterference">non-interfering</a>,
* stateless</a> function for combining two values * <a href="package-summary.html#Statelessness">stateless</a>
* function for combining two values
* @return the result of the reduction * @return the result of the reduction
* @see #sum() * @see #sum()
* @see #min() * @see #min()
...@@ -460,9 +401,10 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -460,9 +401,10 @@ public interface LongStream extends BaseStream<Long, LongStream> {
* <p>This is a <a href="package-summary.html#StreamOps">terminal * <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>. * operation</a>.
* *
* @param op an <a href="package-summary.html#Associativity">associative</a> * @param op an <a href="package-summary.html#Associativity">associative</a>,
* <a href="package-summary.html#NonInterference">non-interfering, * <a href="package-summary.html#NonInterference">non-interfering</a>,
* stateless</a> function for combining two values * <a href="package-summary.html#Statelessness">stateless</a>
* function for combining two values
* @return the result of the reduction * @return the result of the reduction
* @see #reduce(long, LongBinaryOperator) * @see #reduce(long, LongBinaryOperator)
*/ */
...@@ -492,14 +434,15 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -492,14 +434,15 @@ public interface LongStream extends BaseStream<Long, LongStream> {
* @param supplier a function that creates a new result container. For a * @param supplier a function that creates a new result container. For a
* parallel execution, this function may be called * parallel execution, this function may be called
* multiple times and must return a fresh value each time. * multiple times and must return a fresh value each time.
* @param accumulator an <a href="package-summary.html#Associativity">associative</a> * @param accumulator an <a href="package-summary.html#Associativity">associative</a>,
* <a href="package-summary.html#NonInterference">non-interfering, * <a href="package-summary.html#NonInterference">non-interfering</a>,
* stateless</a> function for incorporating an additional * <a href="package-summary.html#Statelessness">stateless</a>
* element into a result * function for incorporating an additional element into a result
* @param combiner an <a href="package-summary.html#Associativity">associative</a> * @param combiner an <a href="package-summary.html#Associativity">associative</a>,
* <a href="package-summary.html#NonInterference">non-interfering, * <a href="package-summary.html#NonInterference">non-interfering</a>,
* stateless</a> function for combining two values, which * <a href="package-summary.html#Statelessness">stateless</a>
* must be compatible with the accumulator function * function for combining two values, which must be
* compatible with the accumulator function
* @return the result of the reduction * @return the result of the reduction
* @see Stream#collect(Supplier, BiConsumer, BiConsumer) * @see Stream#collect(Supplier, BiConsumer, BiConsumer)
*/ */
...@@ -599,48 +542,67 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -599,48 +542,67 @@ public interface LongStream extends BaseStream<Long, LongStream> {
/** /**
* Returns whether any elements of this stream match the provided * Returns whether any elements of this stream match the provided
* predicate. May not evaluate the predicate on all elements if not * predicate. May not evaluate the predicate on all elements if not
* necessary for determining the result. * necessary for determining the result. If the stream is empty then
* {@code false} is returned and the predicate is not evaluated.
* *
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting * <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>. * terminal operation</a>.
* *
* @param predicate a <a href="package-summary.html#NonInterference">non-interfering, * @apiNote
* stateless</a> predicate to apply to elements of this * This method evaluates the <em>existential quantification</em> of the
* stream * predicate over the elements of the stream (for some x P(x)).
*
* @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* predicate to apply to elements of this stream
* @return {@code true} if any elements of the stream match the provided * @return {@code true} if any elements of the stream match the provided
* predicate otherwise {@code false} * predicate, otherwise {@code false}
*/ */
boolean anyMatch(LongPredicate predicate); boolean anyMatch(LongPredicate predicate);
/** /**
* Returns whether all elements of this stream match the provided predicate. * Returns whether all elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for * May not evaluate the predicate on all elements if not necessary for
* determining the result. * determining the result. If the stream is empty then {@code true} is
* returned and the predicate is not evaluated.
* *
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting * <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>. * terminal operation</a>.
* *
* @param predicate a <a href="package-summary.html#NonInterference">non-interfering, * @apiNote
* stateless</a> predicate to apply to elements of this * This method evaluates the <em>universal quantification</em> of the
* stream * predicate over the elements of the stream (for all x P(x)). If the
* @return {@code true} if all elements of the stream match the provided * stream is empty, the quantification is said to be <em>vacuously
* predicate otherwise {@code false} * satisfied</em> and is always {@code true} (regardless of P(x)).
*
* @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* predicate to apply to elements of this stream
* @return {@code true} if either all elements of the stream match the
* provided predicate or the stream is empty, otherwise {@code false}
*/ */
boolean allMatch(LongPredicate predicate); boolean allMatch(LongPredicate predicate);
/** /**
* Returns whether no elements of this stream match the provided predicate. * Returns whether no elements of this stream match the provided predicate.
* May not evaluate the predicate on all elements if not necessary for * May not evaluate the predicate on all elements if not necessary for
* determining the result. * determining the result. If the stream is empty then {@code true} is
* returned and the predicate is not evaluated.
* *
* <p>This is a <a href="package-summary.html#StreamOps">short-circuiting * <p>This is a <a href="package-summary.html#StreamOps">short-circuiting
* terminal operation</a>. * terminal operation</a>.
* *
* @param predicate a <a href="package-summary.html#NonInterference">non-interfering, * @apiNote
* stateless</a> predicate to apply to elements of this * This method evaluates the <em>universal quantification</em> of the
* stream * negated predicate over the elements of the stream (for all x ~P(x)). If
* @return {@code true} if no elements of the stream match the provided * the stream is empty, the quantification is said to be vacuously satisfied
* predicate otherwise {@code false} * and is always {@code true}, regardless of P(x).
*
* @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
* <a href="package-summary.html#Statelessness">stateless</a>
* predicate to apply to elements of this stream
* @return {@code true} if either no elements of the stream match the
* provided predicate or the stream is empty, otherwise {@code false}
*/ */
boolean noneMatch(LongPredicate predicate); boolean noneMatch(LongPredicate predicate);
...@@ -791,12 +753,12 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -791,12 +753,12 @@ public interface LongStream extends BaseStream<Long, LongStream> {
} }
/** /**
* Returns a sequential stream where each element is generated by * Returns an infinite sequential unordered stream where each element is
* the provided {@code LongSupplier}. This is suitable for generating * generated by the provided {@code LongSupplier}. This is suitable for
* constant streams, streams of random elements, etc. * generating constant streams, streams of random elements, etc.
* *
* @param s the {@code LongSupplier} for generated elements * @param s the {@code LongSupplier} for generated elements
* @return a new sequential {@code LongStream} * @return a new infinite sequential unordered {@code LongStream}
*/ */
public static LongStream generate(LongSupplier s) { public static LongStream generate(LongSupplier s) {
Objects.requireNonNull(s); Objects.requireNonNull(s);
...@@ -874,11 +836,16 @@ public interface LongStream extends BaseStream<Long, LongStream> { ...@@ -874,11 +836,16 @@ public interface LongStream extends BaseStream<Long, LongStream> {
/** /**
* Creates a lazily concatenated stream whose elements are all the * Creates a lazily concatenated stream whose elements are all the
* elements of the first stream followed by all the elements of the * elements of the first stream followed by all the elements of the
* second stream. The resulting stream is ordered if both * second stream. The resulting stream is ordered if both
* of the input streams are ordered, and parallel if either of the input * of the input streams are ordered, and parallel if either of the input
* streams is parallel. When the resulting stream is closed, the close * streams is parallel. When the resulting stream is closed, the close
* handlers for both input streams are invoked. * handlers for both input streams are invoked.
* *
* @implNote
* Use caution when constructing streams from repeated concatenation.
* Accessing an element of a deeply concatenated stream can result in deep
* call chains, or even {@code StackOverflowException}.
*
* @param a the first stream * @param a the first stream
* @param b the second stream * @param b the second stream
* @return the concatenation of the two input streams * @return the concatenation of the two input streams
......
...@@ -241,6 +241,7 @@ interface Node<T> { ...@@ -241,6 +241,7 @@ interface Node<T> {
* @param action a consumer that is to be invoked with each * @param action a consumer that is to be invoked with each
* element in this {@code Node.OfPrimitive} * element in this {@code Node.OfPrimitive}
*/ */
@SuppressWarnings("overloads")
void forEach(T_CONS action); void forEach(T_CONS action);
@Override @Override
......
...@@ -579,6 +579,7 @@ class SpinedBuffer<E> ...@@ -579,6 +579,7 @@ class SpinedBuffer<E>
spineIndex = 0; spineIndex = 0;
} }
@SuppressWarnings("overloads")
public void forEach(T_CONS consumer) { public void forEach(T_CONS consumer) {
// completed chunks, if any // completed chunks, if any
for (int j = 0; j < spineIndex; j++) for (int j = 0; j < spineIndex; j++)
......
...@@ -96,7 +96,8 @@ public final class StreamSupport { ...@@ -96,7 +96,8 @@ public final class StreamSupport {
* @param supplier a {@code Supplier} of a {@code Spliterator} * @param supplier a {@code Supplier} of a {@code Spliterator}
* @param characteristics Spliterator characteristics of the supplied * @param characteristics Spliterator characteristics of the supplied
* {@code Spliterator}. The characteristics must be equal to * {@code Spliterator}. The characteristics must be equal to
* {@code supplier.get().characteristics()}. * {@code supplier.get().characteristics()}, otherwise undefined
* behavior may occur when terminal operation commences.
* @param parallel if {@code true} then the returned stream is a parallel * @param parallel if {@code true} then the returned stream is a parallel
* stream; if {@code false} the returned stream is a sequential * stream; if {@code false} the returned stream is a sequential
* stream. * stream.
...@@ -163,7 +164,8 @@ public final class StreamSupport { ...@@ -163,7 +164,8 @@ public final class StreamSupport {
* @param supplier a {@code Supplier} of a {@code Spliterator.OfInt} * @param supplier a {@code Supplier} of a {@code Spliterator.OfInt}
* @param characteristics Spliterator characteristics of the supplied * @param characteristics Spliterator characteristics of the supplied
* {@code Spliterator.OfInt}. The characteristics must be equal to * {@code Spliterator.OfInt}. The characteristics must be equal to
* {@code supplier.get().characteristics()} * {@code supplier.get().characteristics()}, otherwise undefined
* behavior may occur when terminal operation commences.
* @param parallel if {@code true} then the returned stream is a parallel * @param parallel if {@code true} then the returned stream is a parallel
* stream; if {@code false} the returned stream is a sequential * stream; if {@code false} the returned stream is a sequential
* stream. * stream.
...@@ -230,7 +232,8 @@ public final class StreamSupport { ...@@ -230,7 +232,8 @@ public final class StreamSupport {
* @param supplier a {@code Supplier} of a {@code Spliterator.OfLong} * @param supplier a {@code Supplier} of a {@code Spliterator.OfLong}
* @param characteristics Spliterator characteristics of the supplied * @param characteristics Spliterator characteristics of the supplied
* {@code Spliterator.OfLong}. The characteristics must be equal to * {@code Spliterator.OfLong}. The characteristics must be equal to
* {@code supplier.get().characteristics()} * {@code supplier.get().characteristics()}, otherwise undefined
* behavior may occur when terminal operation commences.
* @param parallel if {@code true} then the returned stream is a parallel * @param parallel if {@code true} then the returned stream is a parallel
* stream; if {@code false} the returned stream is a sequential * stream; if {@code false} the returned stream is a sequential
* stream. * stream.
...@@ -297,7 +300,8 @@ public final class StreamSupport { ...@@ -297,7 +300,8 @@ public final class StreamSupport {
* @param supplier A {@code Supplier} of a {@code Spliterator.OfDouble} * @param supplier A {@code Supplier} of a {@code Spliterator.OfDouble}
* @param characteristics Spliterator characteristics of the supplied * @param characteristics Spliterator characteristics of the supplied
* {@code Spliterator.OfDouble}. The characteristics must be equal to * {@code Spliterator.OfDouble}. The characteristics must be equal to
* {@code supplier.get().characteristics()} * {@code supplier.get().characteristics()}, otherwise undefined
* behavior may occur when terminal operation commences.
* @param parallel if {@code true} then the returned stream is a parallel * @param parallel if {@code true} then the returned stream is a parallel
* stream; if {@code false} the returned stream is a sequential * stream; if {@code false} the returned stream is a sequential
* stream. * stream.
......
...@@ -219,31 +219,18 @@ ...@@ -219,31 +219,18 @@
* <em>not modified at all</em> during the execution of the stream pipeline. * <em>not modified at all</em> during the execution of the stream pipeline.
* The notable exception to this are streams whose sources are concurrent * The notable exception to this are streams whose sources are concurrent
* collections, which are specifically designed to handle concurrent modification. * collections, which are specifically designed to handle concurrent modification.
* Concurrent stream sources are those whose {@code Spliterator} reports the
* {@code CONCURRENT} characteristic.
* *
* <p>Accordingly, behavioral parameters passed to stream methods should never * <p>Accordingly, behavioral parameters in stream pipelines whose source might
* modify the stream's data source. An implementation is said to * not be concurrent should never modify the stream's data source.
* <em>interfere</em> with the data source if it modifies, or causes to be * A behavioral parameter is said to <em>interfere</em> with a non-concurrent
* data source if it modifies, or causes to be
* modified, the stream's data source. The need for non-interference applies * modified, the stream's data source. The need for non-interference applies
* to all pipelines, not just parallel ones. Unless the stream source is * to all pipelines, not just parallel ones. Unless the stream source is
* concurrent, modifying a stream's data source during execution of a stream * concurrent, modifying a stream's data source during execution of a stream
* pipeline can cause exceptions, incorrect answers, or nonconformant behavior. * pipeline can cause exceptions, incorrect answers, or nonconformant behavior.
* *
* <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.
*
* For well-behaved stream sources, the source can be modified before the * For well-behaved stream sources, the source can be modified before the
* terminal operation commences and those modifications will be reflected in * terminal operation commences and those modifications will be reflected in
* the covered elements. For example, consider the following code: * the covered elements. For example, consider the following code:
...@@ -265,26 +252,54 @@ ...@@ -265,26 +252,54 @@
* <a href="package-summary.html#StreamSources">Low-level stream * <a href="package-summary.html#StreamSources">Low-level stream
* construction</a> for requirements for building well-behaved streams. * construction</a> for requirements for building well-behaved streams.
* *
* <p>Some streams, particularly those whose stream sources are concurrent, can * <h3><a name="Statelessness">Stateless behaviors</a></h3>
* tolerate concurrent modification during execution of a stream pipeline. *
* However, in no case -- even if the stream source is concurrent -- should * Stream pipeline results may be nondeterministic or incorrect if the behavioral
* behavioral parameters to stream operations modify the stream source. Modifying * parameters to the stream operations are <em>stateful</em>. A stateful lambda
* the stream source from within the stream source may cause pipeline execution * (or other object implementing the appropriate functional interface) is one
* to fail to terminate, produce inaccurate results, or throw exceptions. * whose result depends on any state which might change during the execution
* The following example shows inappropriate interference with the source: * of the stream pipeline. An example of a stateful lambda is the parameter
* to {@code map()} in:
*
* <pre>{@code * <pre>{@code
* // Don't do this! * Set<Integer> seen = Collections.synchronizedSet(new HashSet<>());
* List<String> l = new ArrayList(Arrays.asList("one", "two")); * stream.parallel().map(e -> { if (seen.add(e)) return 0; else return e; })...
* Stream<String> sl = l.stream();
* String s = sl.peek(s -> l.add("BAD LAMBDA")).collect(joining(" "));
* }</pre> * }</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.
*
* <p>Note also that attempting to access mutable state from behavioral parameters
* presents you with a bad choice with respect to safety and performance; if
* you do not synchronize access to that state, you have a data race and
* therefore your code is broken, but if you do synchronize access to that
* state, you risk having contention undermine the parallelism you are seeking
* to benefit from. The best approach is to avoid stateful behavioral
* parameters to stream operations entirely; there is usually a way to
* restructure the stream pipeline to avoid statefulness.
*
* <h3>Side-effects</h3> * <h3>Side-effects</h3>
* *
* Side-effects in behavioral parameters to stream operations are, in general, * Side-effects in behavioral parameters to stream operations are, in general,
* discouraged, as they can often lead to unwitting violations of the * discouraged, as they can often lead to unwitting violations of the
* statelessness requirement, as well as other thread-safety hazards. Many * statelessness requirement, as well as other thread-safety hazards.
* computations where one might be tempted to use side effects can be more *
* <p>If the behavioral parameters do have side-effects, unless explicitly
* stated, there are no guarantees as to the
* <a href="../concurrent/package-summary.html#MemoryVisibility"><i>visibility</i></a>
* of those side-effects to other threads, nor are there any guarantees that
* different operations on the "same" element within the same stream pipeline
* are executed in the same thread. Further, the ordering of those effects
* may be surprising. Even when a pipeline is constrained to produce a
* <em>result</em> that is consistent with the encounter order of the stream
* source (for example, {@code IntStream.range(0,5).parallel().map(x -> x*2).toArray()}
* must produce {@code [0, 2, 4, 6, 8]}), no guarantees are made as to the order
* in which the mapper function is applied to individual elements, or in what
* thread any behavioral parameter is executed for a given element.
*
* <p>Many computations where one might be tempted to use side effects can be more
* safely and efficiently expressed without side-effects, such as using * safely and efficiently expressed without side-effects, such as using
* <a href="package-summary.html#Reduction">reduction</a> instead of mutable * <a href="package-summary.html#Reduction">reduction</a> instead of mutable
* accumulators. However, side-effects such as using {@code println()} for debugging * accumulators. However, side-effects such as using {@code println()} for debugging
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册