提交 ef862ce6 编写于 作者: H henryjen

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
上级 039ade44
......@@ -549,6 +549,7 @@ public interface Collection<E> extends Iterable<E> {
* @return a {@code Spliterator} over the elements in this collection
* @since 1.8
*/
@Override
default Spliterator<E> spliterator() {
return Spliterators.spliterator(this, 0);
}
......
......@@ -105,5 +105,6 @@
* </ul>
*
* @see java.lang.FunctionalInterface
* @since 1.8
*/
package java.util.function;
......@@ -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}:
*
* @param <T> type of stream elements
* @param <S> type of stream implementing {@code BaseStream}
* <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.
*
* <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 @@ public interface BaseStream<T, S extends BaseStream<T, S>>
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 @@ public interface BaseStream<T, S extends BaseStream<T, S>>
/**
* 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>.
......
......@@ -26,6 +26,7 @@ package java.util.stream;
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.Function;
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.
* such as "maximum valued transaction by seller", etc. The class {@link Collectors}
* provides implementations of many common mutable reductions.
*
* <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(", "));
* <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: <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>
*
* // Find highest-paid employee
* Employee highestPaid = employees.stream()
* .collect(Collectors.maxBy(Comparators.comparing(Employee::getSalary)))
* .get();
* <p>Collectors also have a set of characteristics, such as
* {@link Characteristics#CONCURRENT}, that provide hints that can be used by a
* reduction implementation to provide better performance.
*
* // Group employees by department
* Map<Department, List<Employee>> byDept
* = employees.stream()
* .collect(Collectors.groupingBy(Employee::getDepartment));
* <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.
*
* // Find highest-paid employee by department
* Map<Department, Optional<Employee>> highestPaidByDept
* = employees.stream()
* .collect(Collectors.groupingBy(Employee::getDepartment,
* Collectors.maxBy(Comparators.comparing(Employee::getSalary))));
* <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.
*
* // Partition students into passing and failing
* Map<Boolean, List<Student>> passingFailing =
* students.stream()
* .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
* <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())}.
*
* }</pre>
* <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
*
* <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 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>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.
* <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 @@ import java.util.function.Supplier;
* 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 @@ import java.util.function.Supplier;
*
* <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>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)}).
* <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:
*
* TODO Associativity and commutativity
* <pre>{@code
* Collector<Employee, ?, Integer> summingSalaries
* = Collectors.summingInt(Employee::getSalary))
* }</pre>
*
* 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 @@ public interface Collector<T, A, R> {
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 @@ public interface Collector<T, A, R> {
* @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 @@ public interface Collector<T, A, R> {
* @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 @@ public interface Collector<T, A, R> {
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 @@ public interface Collector<T, A, R> {
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,
......
......@@ -62,37 +62,35 @@ import java.util.function.ToLongFunction;
* 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 @@ import java.util.function.ToLongFunction;
*
* }</pre>
*
* TODO explanation of parallel collection
*
* @since 1.8
*/
public final class Collectors {
......@@ -222,7 +218,8 @@ public final class Collectors {
/**
* 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 @@ public final class Collectors {
/**
* 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 @@ public final class Collectors {
* 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>
*
......
......@@ -313,8 +313,8 @@ abstract class DoublePipeline<E_IN>
}
@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 @@ abstract class DoublePipeline<E_IN>
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 @@ abstract class DoublePipeline<E_IN>
}
@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
......
......@@ -349,8 +349,8 @@ abstract class IntPipeline<E_IN>
}
@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 @@ abstract class IntPipeline<E_IN>
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 @@ abstract class IntPipeline<E_IN>
}
@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
......
......@@ -330,8 +330,8 @@ abstract class LongPipeline<E_IN>
}
@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 @@ abstract class LongPipeline<E_IN>
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 @@ abstract class LongPipeline<E_IN>
}
@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
......
......@@ -28,7 +28,7 @@ import java.util.Spliterator;
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.
......
......@@ -170,6 +170,7 @@ abstract class ReferencePipeline<P_IN, P_OUT>
}
@Override
@SuppressWarnings("unchecked")
public void accept(P_OUT u) {
if (predicate.test(u))
downstream.accept(u);
......@@ -263,6 +264,7 @@ abstract class ReferencePipeline<P_IN, P_OUT>
}
@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 @@ abstract class ReferencePipeline<P_IN, P_OUT>
}
@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 @@ abstract class ReferencePipeline<P_IN, P_OUT>
}
@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
......
......@@ -1456,4 +1456,5 @@ class StreamSpliterators {
}
}
}
}
\ No newline at end of file
}
......@@ -32,12 +32,8 @@ import java.util.function.Supplier;
* 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 @@ public final class StreamSupport {
* {@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 @@ public final class StreamSupport {
* <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 @@ public final class StreamSupport {
* {@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 @@ public final class StreamSupport {
* <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 @@ public final class StreamSupport {
* {@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 @@ public final class StreamSupport {
* <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 @@ public final class StreamSupport {
* {@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 @@ public final class StreamSupport {
* <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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册