OpenJDK / lambda / lambda / jdk
changeset 8233:09e54484c80a
Spec pass on Collectors; fix imports; tweak spec on CloseableStream
author | briangoetz |
---|---|
date | Tue, 16 Apr 2013 19:47:46 -0400 |
parents | aa7ac2dee56f |
children | 7bf0e641cea7 d23f3aba300d |
files | src/share/classes/java/util/stream/AbstractPipeline.java src/share/classes/java/util/stream/CloseableStream.java src/share/classes/java/util/stream/Collectors.java src/share/classes/java/util/stream/FindOps.java src/share/classes/java/util/stream/ForEachOps.java src/share/classes/java/util/stream/Nodes.java src/share/classes/java/util/stream/SpinedBuffer.java src/share/classes/java/util/stream/StreamShape.java src/share/classes/java/util/stream/Streams.java src/share/classes/java/util/stream/Tripwire.java src/share/classes/java/util/stream/package-info.java |
diffstat | 11 files changed, 329 insertions(+), 197 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/java/util/stream/AbstractPipeline.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/AbstractPipeline.java Tue Apr 16 19:47:46 2013 -0400 @@ -26,7 +26,8 @@ import java.util.Objects; import java.util.Spliterator; -import java.util.function.*; +import java.util.function.IntFunction; +import java.util.function.Supplier; /** * Abstract base class for "pipeline" classes, which are the core
--- a/src/share/classes/java/util/stream/CloseableStream.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/CloseableStream.java Tue Apr 16 19:47:46 2013 -0400 @@ -30,6 +30,7 @@ * The close method is invoked to release resources that the object is * holding (such as open files). * + * @param <T> The type of stream elements * @since 1.8 */ public interface CloseableStream<T> extends Stream<T>, AutoCloseable { @@ -37,7 +38,8 @@ /** * Closes this resource, relinquishing any underlying resources. * This method is invoked automatically on objects managed by the - * {@code try}-with-resources statement. + * {@code try}-with-resources statement. Does nothing if called when + * the resource has already been closed. * * This method does not allow throwing checked {@code Exception} like * {@link AutoCloseable#close() AutoCloseable.close()}. Cases where the
--- a/src/share/classes/java/util/stream/Collectors.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/Collectors.java Tue Apr 16 19:47:46 2013 -0400 @@ -60,7 +60,45 @@ * operations, such as accumulating elements into collections, summarizing * elements according to various criteria, etc. * - * TODO mini-tutorial + * <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 elements into a List + * List list = stream.collect(Collectors.toList()); + * + * // Accumulate elements into a TreeSet + * List list = stream.collect(Collectors.toCollection(TreeSet::new)); + * + * // Convert elements to strings and concatenate them, separated by commas + * String joined = stream.map(Object::toString) + * .collect(Collectors.toStringJoiner(", ")) + * .toString(); + * + * // Find highest-paid employee + * Employee highestPaid = employees.stream() + * .collect(Collectors.maxBy(Comparators.comparing(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, Employee> highestPaidByDept + * = employees.stream() + * .collect(Collectors.groupingBy(Employee::getDepartment, + * Collectors.maxBy(Comparators.comparing(Employee::getSalary)))); + * + * // Partition students into passing and failing + * Map<Boolean, List<Student>> passingFailing = + * students.stream() + * .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD); + * + * }</pre> + * + * TODO explanation of parallel collection * * @since 1.8 */ @@ -68,7 +106,8 @@ private static final Set<Collector.Characteristics> CH_CONCURRENT = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT, - Collector.Characteristics.STRICTLY_MUTATIVE)); + Collector.Characteristics.STRICTLY_MUTATIVE, + Collector.Characteristics.UNORDERED)); private static final Set<Collector.Characteristics> CH_STRICT = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.STRICTLY_MUTATIVE)); private static final Set<Collector.Characteristics> CH_STRICT_UNORDERED @@ -78,10 +117,10 @@ private Collectors() { } /** - * Return a merge function, suitable for use in - * {@link Map#merge(Object, Object, BiFunction)} or - * {@link #toMap(Function, Function, BinaryOperator)}, which always throws - * {@code IllegalStateException}. This can be used to enforce the + * Returns a merge function, suitable for use in + * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or + * {@link #toMap(Function, Function, BinaryOperator) toMap()}, which always + * throws {@code IllegalStateException}. This can be used to enforce the * assumption that the elements being collected are distinct. * * @param <T> The type of input arguments to the merge function @@ -92,10 +131,10 @@ } /** - * Return a merge function, suitable for use in - * {@link Map#merge(Object, Object, BiFunction)} or - * {@link #toMap(Function, Function, BinaryOperator)}, which implements a - * "first wins" policy. + * Returns a merge function, suitable for use in + * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or + * {@link #toMap(Function, Function, BinaryOperator) toMap()}, + * which implements a "first wins" policy. * * @param <T> The type of input arguments to the merge function * @return A merge function which always returns its first argument @@ -105,10 +144,10 @@ } /** - * Return a merge function, suitable for use in - * {@link Map#merge(Object, Object, BiFunction)} or - * {@link #toMap(Function, Function, BinaryOperator)}, which implements a - * "last wins" policy. + * Returns a merge function, suitable for use in + * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or + * {@link #toMap(Function, Function, BinaryOperator) toMap()}, + * which implements a "last wins" policy. * * @param <T> The type of input arguments to the merge function * @return A merge function which always returns its second argument @@ -117,7 +156,7 @@ return (u,v) -> v; } - /** Simple implementation class for {@code Collector} */ + /** Simple implementation class for {@code Collector}. */ private static final class CollectorImpl<T, R> implements Collector<T,R> { private final Supplier<R> resultSupplier; private final BiFunction<R, T, R> accumulator; @@ -162,8 +201,8 @@ } /** - * Return a {@code Collector} that accumulates the input elements into a new - * {@code Collection}, in encounter order. The {@code Collection} is + * Returns a {@code Collector} that accumulates the input elements into a + * new {@code Collection}, in encounter order. The {@code Collection} is * created by the provided factory. * * @param collectionFactory A {@code Supplier} which returns a new, empty @@ -182,9 +221,9 @@ } /** - * Return a {@code Collector} that accumulates the input elements into a - * {@code List}. There are no guarantees on the type of the {@code List} - * returned, and the returned list is not guaranteed to be mutable. + * 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. * * @param <T> The type of the input elements * @return A {@code Collector} which collects all the input elements into a @@ -224,9 +263,9 @@ } /** - * Return a {@code Collector} that accumulates the input elements into a - * {@code Set}. There are no guarantees on the type of the {@code Set} - * returned, and the returned list is not guaranteed to be mutable. + * 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. * * @param <T> The type of the input elements * @return A {@code Collector} which collects all the input elements into a @@ -241,7 +280,7 @@ } /** - * Return a {@code Collector} that concatenates the input elements into a + * Returns a {@code Collector} that concatenates the input elements into a * new {@code StringBuilder}. * * @return A {@code Collector} which collects String elements into a @@ -255,7 +294,7 @@ } /** - * Return a {@code Collector} that concatenates the input elements into a + * Returns a {@code Collector} that concatenates the input elements into a * new {@code StringJoiner}, using the specified separator. * * @return A {@code Collector} which collects String elements into a @@ -267,21 +306,24 @@ sj.add(other.toString()); return sj; }; - return new CollectorImpl<>(() -> new StringJoiner(separator), (r, t) -> { r.add(t); return r; }, + return new CollectorImpl<>(() -> new StringJoiner(separator), + (r, t) -> { r.add(t); return r; }, merger, CH_STRICT); } - /** BinaryOperator<Map> that merges the contents of its right argument into - * its left argument, using the provided merge function to handle duplicate - * keys + /** + * {@code BinaryOperator<Map>} that merges the contents of its right + * argument into its left argument, using the provided merge function to + * handle duplicate keys. * @param mergeFunction A merge function suitable for - * {@link Map#merge(Object, Object, BiFunction)} + * {@link Map#merge(Object, Object, BiFunction) Map.merge()} * @param <K> Type of the map keys * @param <V> Type of the map values * @param <M> Type of the map * @return A merge function for two maps */ - private static<K, V, M extends Map<K,V>> BinaryOperator<M> mapMerger(BinaryOperator<V> mergeFunction) { + private static<K, V, M extends Map<K,V>> + BinaryOperator<M> mapMerger(BinaryOperator<V> mergeFunction) { return (m1, m2) -> { for (Map.Entry<K,V> e : m2.entrySet()) m1.merge(e.getKey(), e.getValue(), mergeFunction); @@ -291,12 +333,12 @@ /** * Adapts a {@code Collector<U,R>} to a {@code Collector<T,R>} by applying - * a mapping function to each input element before the accumulation step. + * a mapping function to each input element before accumulation. * * @apiNote - * The {@code mapping()} collectors are often useful when used in a - * multi-level collection downstream of a {@code groupingBy} or - * {@code partitioningBy} collection. For example, given a stream of + * The {@code mapping()} collectors are most useful when used in a + * multi-level reduction, downstream of {@code groupingBy} or + * {@code partitioningBy}. For example, given a stream of * {@code Person}, to accumulate the set of last names in each city: * <pre>{@code * Map<City, Set<String>> lastNamesByCity @@ -307,10 +349,10 @@ * @param <T> The type of the input elements * @param <U> Type of elements accepted by downstream collector * @param <R> Result type of collector - * @param mapper A function mapping {@code T} to {@code U} - * @param downstream collector which will accept mapped values - * @return A collector which applies the mapping function to input elements - * and then provides them to the downstream collector + * @param mapper A function to be applied to the input elements + * @param downstream A collector which will accept mapped values + * @return A collector which applies the mapping function to the input + * elements and provides the mapped results to the downstream collector */ public static <T, U, R> Collector<T, R> mapping(Function<? super T, ? extends U> mapper, Collector<U, R> downstream) { @@ -321,7 +363,7 @@ } /** - * Produces a {@code Collector<T, Long>} that counts the number of input + * Returns a {@code Collector<T, Long>} that counts the number of input * elements. * * @implSpec @@ -330,7 +372,7 @@ * reducing(0L, e -> 1L, Long::sum) * }</pre> * @param <T> The type of the input elements - * @return A {@code Collector} that counts its input elements + * @return A {@code Collector} that counts the input elements */ public static<T> Collector<T, Long> counting() { @@ -338,7 +380,7 @@ } /** - * Produces a {@code Collector<T, T>} that produces the minimal element + * Returns a {@code Collector<T, T>} that produces the minimal element * according to a given {@code Comparator}. * * @implSpec @@ -348,7 +390,7 @@ * }</pre> * @param <T> The type of the input elements * @param comparator A {@code Comparator} for comparing elements - * @return A {@code Collector} that produces the maximal value + * @return A {@code Collector} that produces the minimal value */ public static<T> Collector<T, T> minBy(Comparator<? super T> comparator) { @@ -356,7 +398,7 @@ } /** - * Produces a {@code Collector<T, T>} that produces the maximal element + * Returns a {@code Collector<T, T>} that produces the maximal element * according to a given {@code Comparator}. * * @implSpec @@ -374,7 +416,7 @@ } /** - * Produces a {@code Collector<T, Long>} that produces the sum of an + * Returns a {@code Collector<T, Long>} that produces the sum of a * long-valued function applied to the input element. * * @implSpec @@ -392,16 +434,16 @@ } /** - * Produces a {@code Collector<T,T>} which implements a reduction of its + * Returns a {@code Collector<T,T>} which performs a reduction of its * input elements under a specified {@code BinaryOperator}. * * @apiNote * The {@code reducing()} collectors are most useful when used in a - * multi-level collection following a {@code groupingBy} or - * {@code partitioningBy} collection; if you want to perform a simple - * reduction on a stream, use {@link Stream#reduce(BinaryOperator)}. + * multi-level reduction, downstream of {@code groupingBy} or + * {@code partitioningBy}. To perform a simple reduction on a stream, + * use {@link Stream#reduce(BinaryOperator)} instead. * @param identity The identity value for the reduction (also, the value - * that is returned when there are no elements to reduce) + * that is returned when there are no input elements) * @param op A {@code BinaryOperator<T>} used to reduce the input elements * @return A {@code Collector} which implements the reduction operation * @see #reducing(Object, Function, BinaryOperator) @@ -412,16 +454,16 @@ } /** - * Given a {@code BinaryOperator<T>}, return a {@code Collector<T,T>} which - * calculates the reduction of its input elements under the specified - * {@code BinaryOperator}. + * Returns a {@code Collector<T,T>} which performs a reduction of its + * input elements under a specified {@code BinaryOperator}. * * @apiNote * The {@code reducing()} collectors are most useful when used in a - * multi-level collection following a {@code groupingBy} or - * {@code partitioningBy} collection; if you want to perform a simple - * reduction on a stream, use {@link Stream#reduce(BinaryOperator)}. - * For example, given a stream of {@code Person}, to calculate tallest + * multi-level reduction, downstream of {@code groupingBy} or + * {@code partitioningBy}. To perform a simple reduction on a stream, + * use {@link Stream#reduce(BinaryOperator)} instead. + * + * <p>For example, given a stream of {@code Person}, to calculate tallest * person in each city: * <pre>{@code * Comparator<Person> byHeight = Comparators.comparing(Person::getHeight); @@ -439,18 +481,19 @@ } /** - * Given a {@code BinaryOperator<U>} and a {@code Function<T,U>}, return a - * {@code Collector<T,U>} which calculates the reduction of the input - * elements after applying the mapping function. This is a generalization of - * {@link #reducing(Object, BinaryOperator)} which allows a transformation of - * the elements before reduction. + * Returns a {@code Collector<T,U>} which performs a reduction of its + * input elements under a specified mapping function and + * {@code BinaryOperator}. This is a generalization of + * {@link #reducing(Object, BinaryOperator)} which allows a transformation + * of the elements before reduction. * * @apiNote * The {@code reducing()} collectors are most useful when used in a - * multi-level collection following a {@code groupingBy} or - * {@code partitioningBy} collection; if you want to perform a simple - * reduction on a stream, use {@link Stream#reduce(BinaryOperator)}. - * For example, given a stream of {@code Person}, to calculate the longest + * multi-level reduction, downstream of {@code groupingBy} or + * {@code partitioningBy}. To perform a simple reduction on a stream, + * use {@link Stream#reduce(BinaryOperator)} instead. + * + * <p>For example, given a stream of {@code Person}, to calculate the longest * last name of residents in each city: * <pre>{@code * Comparator<String> byLength = Comparators.comparing(String::length); @@ -461,7 +504,7 @@ * }</pre> * * @param mapper A mapping function to apply to each input value - * @param op A {@code BinaryOperator<T>} used to reduce the mapped values + * @param op A {@code BinaryOperator<U>} used to reduce the mapped values * @param <T> The type of the input elements * @param <U> The type of the mapped values * @return A {@code Collector} implementing the map-reduce operation @@ -478,19 +521,18 @@ /** * Returns a {@code Collector} implementing a "group by" operation on - * input elements of type {@code T}, categorizing elements according to a - * classification function and accumulating all elements in a category - * into a {@code List} and placing the results in a {@code Map}. + * input elements of type {@code T}, grouping elements according to a + * classification function. * - * <p>THe classification function maps elements to some key type {@code K}. + * <p>The classification function maps elements to some key type {@code K}. * The collector produces a {@code Map<K, List<T>>} whose keys are the set * of values resulting from applying the classification function to the input * elements, and whose corresponding values are {@code List}s containing the * input elements which map to the associated key under the classification * function. * - * <p>No guarantees are made as to the type of the {@code Map} or the type - * of the {@code List} used for the map values. + * <p>No guarantees are made as to the type of the {@code Map} or + * {@code List} objects. * * @param classifier The classifier function mapping input elements to keys * @param <T> The type of the input elements @@ -503,15 +545,23 @@ } /** - * Returns a {@code Collector} that implements a cascaded "group by" operation on input elements - * of type {@code T}, resulting in a {@code Map} whose values are the result of another reduction, - * resulting in a {@code Map} of a specific type. + * Returns a {@code Collector} implementing a cascaded "group by" operation + * on input elements of type {@code T}, grouping elements according to a + * classification function, and then performing a reduction operation on + * the values associated with a given key using the specified downstream + * {@code Collector}. * - * <p>Accepts a classification function from {@code T} to {@code K} and a {@code Collector} which implements - * another reduction on elements of type {@code T}. The collector populates a {@code Map} - * whose keys are the set of values resulting of applying the classification function to the input elements, - * and whose corresponding values are the result of reducing the input elements which map to the associated key - * under the classification function with the dowstream reducer. + * <p>The classification function maps elements to some key type {@code K}. + * The downstream collector operates on elements of type {@code T} and + * produces a result of type {@code D}. The resulting collector produces a + * {@code Map<K, D>}. + * + * <p>For example, to compute the set of last names of people in each city: + * <pre>{@code + * Map<City, Set<String>> namesByCity + * = people.stream().collect(groupingBy(Person::getCity, + * mapping(Person::getLastName, toSet()))); + * }</pre> * * <p>No guarantees are made as to the type of the resulting {@code Map}. * @@ -529,18 +579,30 @@ } /** - * Returns a {@code Collector} that implements a cascaded "group by" operation on input elements - * of type {@code T}, resulting in a {@code Map} whose values are the result of another reduction. + * Returns a {@code Collector} implementing a cascaded "group by" operation + * on input elements of type {@code T}, grouping elements according to a + * classification function, and then performing a reduction operation on + * the values associated with a given key using the specified downstream + * {@code Collector}. The {@code Map} produced by the Collector is created + * with the supplied factory function. * - * <p>Accepts a classification function from {@code T} to {@code K}, a factory function which produces - * a {@code Map} of the desired type, and a {@code Collector} which implements another reduction on elements - * of type {@code T}. The collector populates a {@code Map} produced by the factory function - * whose keys are the set of values resulting of applying the classification function to the input elements, - * and whose corresponding values are the result of reducing the input elements which map to the associated key - * under the classification function with the dowstream reducer. + * <p>The classification function maps elements to some key type {@code K}. + * The downstream collector operates on elements of type {@code T} and + * produces a result of type {@code D}. The resulting collector produces a + * {@code Map<K, D>}. + * + * <p>For example, to compute the set of last names of people in each city, + * where the city names are sorted: + * <pre>{@code + * Map<City, Set<String>> namesByCity + * = people.stream().collect(groupingBy(Person::getCity, TreeMap::new, + * mapping(Person::getLastName, toSet()))); + * }</pre> * * @param classifier The classifier function mapping input elements to keys * @param downstream A {@code Collector} implementing the downstream reduction + * @param mapFactory A function which, when called, produces a new empty + * {@code Map} of the desired type * @param <T> The type of the input elements * @param <K> The type of the keys * @param <D> The result type of the downstream reduction @@ -564,18 +626,22 @@ } /** - * Returns a {@code Collector} that implements a concurrent "group by" operation on input - * elements of type {@code T}. - * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} Collector. + * Returns a {@code Collector} implementing a concurrent "group by" + * operation on input elements of type {@code T}, grouping elements + * according to a classification function. * - * <p>Accepts a classification function from {@code T} to {@code K}. The collector produces - * a {@code ConcurrentMap} whose keys are the set of values resulting of applying the - * classification function to the input elements, and whose corresponding values are - * {@code List}s containing the input elements which map to the associated key under the - * classification function. + * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and + * {@link Collector.Characteristics#UNORDERED unordered} Collector. * - * <p>No guarantees are made as to the type of the {@code ConcurrentMap} or the type of the - * {@code List} used for the map values. + * <p>The classification function maps elements to some key type {@code K}. + * The collector produces a {@code ConcurrentMap<K, List<T>>} whose keys are the set + * of values resulting from applying the classification function to the input + * elements, and whose corresponding values are {@code List}s containing the + * input elements which map to the associated key under the classification + * function. + * + * <p>No guarantees are made as to the type of the {@code Map} or + * {@code List} objects. * * @param classifier The classifier function mapping input elements to keys * @param <T> The type of the input elements @@ -588,19 +654,27 @@ } /** - * Returns a {@code Collector} that implements a concurrent cascaded "group by" operation on - * input elements of type {@code T}, resulting in a {@code ConcurrentMap} whose values are - * the result of another reduction, resulting in a {@code ConcurrentMap} of a specific type. - * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} Collector. + * Returns a {@code Collector} implementing a concurrent cascaded "group by" + * operation on input elements of type {@code T}, grouping elements + * according to a classification function, and then performing a reduction + * operation on the values associated with a given key using the specified + * downstream {@code Collector}. * - * <p>Accepts a classification function from {@code T} to {@code K} and a {@code Collector} - * which implements another reduction on elements of type {@code T}. The collector populates - * a {@code ConcurrentMap} whose keys are the set of values resulting of applying the - * classification function to the input elements, and whose corresponding values are the - * result of reducing the input elements which map to the associated key under the - * classification function with the dowstream reducer. + * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and + * {@link Collector.Characteristics#UNORDERED unordered} Collector. * - * <p>No guarantees are made as to the type of the resulting {@code Map}. + * <p>The classification function maps elements to some key type {@code K}. + * The downstream collector operates on elements of type {@code T} and + * produces a result of type {@code D}. The resulting collector produces a + * {@code Map<K, D>}. + * + * <p>For example, to compute the set of last names of people in each city, + * where the city names are sorted: + * <pre>{@code + * ConcurrentMap<City, Set<String>> namesByCity + * = people.stream().collect(groupingByConcurrent(Person::getCity, TreeMap::new, + * mapping(Person::getLastName, toSet()))); + * }</pre> * * @param classifier The classifier function mapping input elements to keys * @param downstream A {@code Collector} implementing the downstream reduction @@ -616,18 +690,29 @@ } /** - * Returns a {@code Collector} that implements a cascaded concurrent "group by" operation on - * input elements of type {@code T}, resulting in a {@code ConcurrentMap} whose values are - * the result of another reduction. - * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} Collector. + * Returns a concurrent {@code Collector} implementing a cascaded "group by" + * operation on input elements of type {@code T}, grouping elements + * according to a classification function, and then performing a reduction + * operation on the values associated with a given key using the specified + * downstream {@code Collector}. The {@code ConcurrentMap} produced by the + * Collector is created with the supplied factory function. * - * <p>Accepts a classification function from {@code T} to {@code K}, a factory function - * which produces a {@code ConcurrentMap} of the desired type, and a {@code Collector} which - * implements another reduction on elements of type {@code T}. The collector populates a - * {@code ConcurrentMap} produced by the factory function whose keys are the set of values - * resulting of applying the classification function to the input elements, and whose - * corresponding values are the result of reducing the input elements which map to the - * associated key under the classification function with the dowstream reducer. + * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and + * {@link Collector.Characteristics#UNORDERED unordered} Collector. + * + * <p>The classification function maps elements to some key type {@code K}. + * The downstream collector operates on elements of type {@code T} and + * produces a result of type {@code D}. The resulting collector produces a + * {@code Map<K, D>}. + * + * <p>For example, to compute the set of last names of people in each city, + * where the city names are sorted: + * <pre>{@code + * ConcurrentMap<City, Set<String>> namesByCity + * = people.stream().collect(groupingBy(Person::getCity, ConcurrentSkipListMap::new, + * mapping(Person::getLastName, toSet()))); + * }</pre> + * * * @param classifier The classifier function mapping input elements to keys * @param downstream A {@code Collector} implementing the downstream reduction @@ -688,10 +773,12 @@ } /** - * Return a {@code Collector} which partitions the input elements according to a {@code Predicate}, and - * organizes them into a {@code Map<Boolean, List<T>>}. + * Returns a {@code Collector} which partitions the input elements according + * to a {@code Predicate}, and organizes them into a + * {@code Map<Boolean, List<T>>}. * - * <p>No guarantee is made as to the type of the returned {@code Map}, and it is not guaranteed to be mutable. + * <p>No guarantee is made as to the type of the returned {@code Map}, and + * it is not guaranteed to be mutable. * * @param predicate The predicate used for classifying input elements * @param <T> The type of the input elements @@ -703,11 +790,14 @@ } /** - * Return a {@code Collector} which partitions the input elements according to a {@code Predicate}, - * computes another reduction on the partitioned elements, and organizes them into - * a {@code Map<Boolean, D>} whose values are the result of the downstream reduction. + * Returns a {@code Collector} which partitions the input elements according + * to a {@code Predicate}, reduces the values in each partition according to + * another {@code Collector}, and organizes them into a + * {@code Map<Boolean, D>} whose values are the result of the downstream + * reduction. * - * <p>No guarantee is made as to the type of the returned {@code Map}, and it is not guaranteed to be mutable. + * <p>No guarantee is made as to the type of the returned {@code Map}, and + * it is not guaranteed to be mutable. * * @param predicate The predicate used for classifying input elements * @param downstream A {@code Collector} implementing the downstream reduction @@ -738,7 +828,7 @@ accumulator, partitionMerger(downstream.combiner()), CH_STRICT); } - /** Merge function for two partitions, given a merge function for the elements */ + /** Merge function for two partitions, given a merge function for the elements. */ private static<D> BinaryOperator<Map<Boolean, D>> partitionMerger(BinaryOperator<D> op) { return (m1, m2) -> { Partition<D> left = (Partition<D>) m1; @@ -767,8 +857,8 @@ * @apiNote * It is common for either the key or the value to be the input elements. * In this case, the utility method - * {@link java.util.function.Functions#identity()} is likely - * to be helpful. For example, the following produces a {@code Map} mapping + * {@link java.util.function.Functions#identity()} may be helpful. + * For example, the following produces a {@code Map} mapping * students to their grade point average: * <pre>{@code * Map<Student, Double> studentToGPA @@ -788,9 +878,8 @@ * @param keyMapper The mapping function to produce keys * @param valueMapper The mapping function to produce values * @return A {@code Collector} which collects elements into a {@code Map} - * whose keys are the result of applying a key mapping function to the input - * elements, and whose values are the result of applying a value mapping - * function to the input elements + * whose keys and values are the result of applying mapping functions to + * the input elements */ public static <T, K, U> Collector<T, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, @@ -803,7 +892,7 @@ * result of applying mapping functions to the input elements. If the mapped * keys contains duplicates (according to {@link Object#equals(Object)}), * the value mapping function is applied to each equal element, and the - * results are merged with the provided merging function. + * results are merged using the provided merging function. * * @apiNote * There are multiple ways to deal with collisions between multiple elements @@ -811,9 +900,10 @@ * such as {@link #throwingMerger()}, {@link #firstWinsMerger()}, and * {@link #lastWinsMerger()}, that implement common policies, or you can * implement custom policies easily. For example, if you have a stream - * of Person, and you want to produce a "phone book" mapping name to address, - * but it is possible that two persons have the same name, you can do - * as follows to gracefully deals with these collisions: + * of {@code Person}, and you want to produce a "phone book" mapping name to + * address, but it is possible that two persons have the same name, you can + * do as follows to gracefully deals with these collisions, and produce a + * {@code Map} mapping names to a concatened list of addresses: * <pre>{@code * Map<String, String> phoneBook * people.stream().collect(toMap(Person::getName, @@ -846,7 +936,7 @@ * result of applying mapping functions to the input elements. If the mapped * keys contains duplicates (according to {@link Object#equals(Object)}), * the value mapping function is applied to each equal element, and the - * results are merged with 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. * * @param <T> The type of the input elements @@ -885,10 +975,30 @@ * If the mapped keys contains duplicates (according to * {@link Object#equals(Object)}), an {@code IllegalStateException} is * thrown when the collection operation is performed. If the mapped keys - * may have duplicates, use {@link #toConcurrentMap(Function, Function, BinaryOperator)} - * instead. + * may have duplicates, use + * {@link #toConcurrentMap(Function, Function, BinaryOperator)} instead. * - * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} Collector. + * @apiNote + * It is common for either the key or the value to be the input elements. + * In this case, the utility method + * {@link java.util.function.Functions#identity()} may be helpful. + * For example, the following produces a {@code Map} mapping + * students to their grade point average: + * <pre>{@code + * Map<Student, Double> studentToGPA + * students.stream().collect(toMap(Functions.identity(), + * student -> computeGPA(student))); + * }</pre> + * And the following produces a {@code Map} mapping a unique identifier to + * students: + * <pre>{@code + * Map<String, Student> studentIdToStudent + * students.stream().collect(toConcurrentMap(Student::getId, + * Functions.identity()); + * }</pre> + * + * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and + * {@link Collector.Characteristics#UNORDERED unordered} Collector. * * @param <T> The type of the input elements * @param <K> The output type of the key mapping function @@ -909,12 +1019,29 @@ /** * Accumulate elements into a {@code ConcurrentMap} whose keys and values * are the result of applying mapping functions to the input elements. If - * the mapped keys contains duplicates (according to - * {@link Object#equals(Object)}), the value mapping function is applied to - * each equal element, and the results are merged with the provided merging - * function. + * the mapped keys contains duplicates (according to {@link Object#equals(Object)}), + * the value mapping function is applied to each equal element, and the + * results are merged using the provided merging function. * - * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} Collector. + * @apiNote + * There are multiple ways to deal with collisions between multiple elements + * mapping to the same key. There are some predefined merging functions, + * such as {@link #throwingMerger()}, {@link #firstWinsMerger()}, and + * {@link #lastWinsMerger()}, that implement common policies, or you can + * implement custom policies easily. For example, if you have a stream + * of {@code Person}, and you want to produce a "phone book" mapping name to + * address, but it is possible that two persons have the same name, you can + * do as follows to gracefully deals with these collisions, and produce a + * {@code Map} mapping names to a concatened list of addresses: + * <pre>{@code + * Map<String, String> phoneBook + * people.stream().collect(toConcurrentMap(Person::getName, + * Person::getAddress, + * (s, a) -> s + ", " + a)); + * }</pre> + * + * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and + * {@link Collector.Characteristics#UNORDERED unordered} Collector. * * @param <T> The type of the input elements * @param <K> The output type of the key mapping function @@ -940,12 +1067,13 @@ /** * Accumulate elements into a {@code ConcurrentMap} whose keys and values * are the result of applying mapping functions to the input elements. If - * the mapped keys contains duplicates (according to - * {@link Object#equals(Object)}), the value mapping function is applied to - * each equal element, and the results are merged with the provided merging - * function. The {@code ConcurrentMap} is created by a provided supplier function. + * the mapped keys contains duplicates (according to {@link Object#equals(Object)}), + * the value mapping function is applied to each equal element, and the + * results are merged using the provided merging function. The + * {@code ConcurrentMap} is created by a provided supplier function. * - * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} Collector. + * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and + * {@link Collector.Characteristics#UNORDERED unordered} Collector. * * @param <T> The type of the input elements * @param <K> The output type of the key mapping function @@ -976,12 +1104,14 @@ } /** - * Return a {@code Collector} which applies an {@code int}-producing mapping function to each input - * element, and returns summary statistics for the resulting values. + * Returns a {@code Collector} which applies an {@code int}-producing + * mapping function to each input element, and returns summary statistics + * for the resulting values. * * @param mapper The mapping function to apply to each element * @param <T> The type of the input elements * @return A {@code Collector} implementing the summary-statistics reduction + * @see IntSummaryStatistics */ public static<T> Collector<T, IntSummaryStatistics> toIntSummaryStatistics(ToIntFunction<? super T> mapper) { @@ -991,12 +1121,14 @@ } /** - * Return a {@code Collector} which applies an {@code long}-producing mapping function to each input - * element, and returns summary statistics for the resulting values. + * Returns a {@code Collector} which applies an {@code long}-producing + * mapping function to each input element, and returns summary statistics + * for the resulting values. * * @param mapper The mapping function to apply to each element * @param <T> The type of the input elements * @return A {@code Collector} implementing the summary-statistics reduction + * @see LongSummaryStatistics */ public static<T> Collector<T, LongSummaryStatistics> toLongSummaryStatistics(ToLongFunction<? super T> mapper) { @@ -1006,12 +1138,14 @@ } /** - * Return a {@code Collector} which applies an {@code double}-producing mapping function to each input - * element, and returns summary statistics for the resulting values. + * Returns a {@code Collector} which applies an {@code double}-producing + * mapping function to each input element, and returns summary statistics + * for the resulting values. * * @param mapper The mapping function to apply to each element * @param <T> The type of the input elements * @return A {@code Collector} implementing the summary-statistics reduction + * @see DoubleSummaryStatistics */ public static<T> Collector<T, DoubleSummaryStatistics> toDoubleSummaryStatistics(ToDoubleFunction<? super T> mapper) { @@ -1020,6 +1154,7 @@ (l, r) -> { l.combine(r); return l; }, CH_STRICT); } + /** Implementation class used by partitioningBy. */ private static final class Partition<T> extends AbstractMap<Boolean, T> implements Map<Boolean, T> { @@ -1031,34 +1166,12 @@ this.forFalse = forFalse; } - final class Entry implements Map.Entry<Boolean, T> { - private final int state; - - Entry(int state) { - this.state = state; - } - - @Override - public Boolean getKey() { - return state == 1; - } - - @Override - public T getValue() { - return state == 0 ? forFalse : forTrue; - } - - @Override - public T setValue(T value) { - throw new UnsupportedOperationException(); - } - } - @Override public Set<Map.Entry<Boolean, T>> entrySet() { return new AbstractSet<Map.Entry<Boolean, T>>() { @Override public Iterator<Map.Entry<Boolean, T>> iterator() { + return new Iterator<Map.Entry<Boolean, T>>() { int state = 0; @@ -1069,10 +1182,11 @@ @Override public Map.Entry<Boolean, T> next() { - if (state < 2) - return new Entry(state++); - else + if (state >= 2) throw new NoSuchElementException(); + return (state++ == 0) + ? new SimpleImmutableEntry<>(false, forFalse) + : new SimpleImmutableEntry<>(true, forTrue); } }; }
--- a/src/share/classes/java/util/stream/FindOps.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/FindOps.java Tue Apr 16 19:47:46 2013 -0400 @@ -24,7 +24,11 @@ */ package java.util.stream; -import java.util.*; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.OptionalLong; +import java.util.Spliterator; import java.util.concurrent.CountedCompleter; import java.util.function.Predicate; import java.util.function.Supplier;
--- a/src/share/classes/java/util/stream/ForEachOps.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/ForEachOps.java Tue Apr 16 19:47:46 2013 -0400 @@ -24,6 +24,7 @@ */ package java.util.stream; +import java.util.Objects; import java.util.Spliterator; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountedCompleter; @@ -31,7 +32,6 @@ import java.util.function.DoubleConsumer; import java.util.function.IntConsumer; import java.util.function.LongConsumer; -import java.util.Objects; /** * Factory for creating instances of {@code TerminalOp} that perform an
--- a/src/share/classes/java/util/stream/Nodes.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/Nodes.java Tue Apr 16 19:47:46 2013 -0400 @@ -24,7 +24,13 @@ */ package java.util.stream; -import java.util.*; +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Collection; +import java.util.Deque; +import java.util.List; +import java.util.Objects; +import java.util.Spliterator; import java.util.Spliterators; import java.util.concurrent.CountedCompleter; import java.util.function.Consumer;
--- a/src/share/classes/java/util/stream/SpinedBuffer.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/SpinedBuffer.java Tue Apr 16 19:47:46 2013 -0400 @@ -24,7 +24,12 @@ */ package java.util.stream; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.PrimitiveIterator; +import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; import java.util.function.DoubleConsumer;
--- a/src/share/classes/java/util/stream/StreamShape.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/StreamShape.java Tue Apr 16 19:47:46 2013 -0400 @@ -24,8 +24,6 @@ */ package java.util.stream; -import java.util.function.ToIntFunction; - /** * An enum describing the known shape specializations for stream abstractions. * Each will correspond to a specific subinterface of {@link BaseStream}
--- a/src/share/classes/java/util/stream/Streams.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/Streams.java Tue Apr 16 19:47:46 2013 -0400 @@ -24,7 +24,11 @@ */ package java.util.stream; -import java.util.*; +import java.util.Comparator; +import java.util.Iterator; +import java.util.Objects; +import java.util.PrimitiveIterator; +import java.util.Spliterator; import java.util.Spliterators; import java.util.function.BiFunction; import java.util.function.Consumer;
--- a/src/share/classes/java/util/stream/Tripwire.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/Tripwire.java Tue Apr 16 19:47:46 2013 -0400 @@ -24,11 +24,11 @@ */ package java.util.stream; -import sun.util.logging.PlatformLogger; - import java.security.AccessController; import java.security.PrivilegedAction; +import sun.util.logging.PlatformLogger; + /** * Utility class for detecting inadvertent uses of boxing in * {@code java.util.stream} classes. The detection is turned on or off based on
--- a/src/share/classes/java/util/stream/package-info.java Tue Apr 16 14:52:13 2013 -0700 +++ b/src/share/classes/java/util/stream/package-info.java Tue Apr 16 19:47:46 2013 -0400 @@ -560,5 +560,3 @@ package java.util.stream; -import java.util.function.BiConsumer; -import java.util.function.Supplier; \ No newline at end of file