src/share/classes/java/util/stream/Collectors.java

Print this page
rev 7485 : 8009736: Comparator API cleanup
Reviewed-by:
Contributed-by: henry.jen@oracle.com


  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.util.stream;
  26 
  27 import java.util.AbstractMap;
  28 import java.util.AbstractSet;
  29 import java.util.ArrayList;
  30 import java.util.Collection;
  31 import java.util.Collections;
  32 import java.util.Comparator;
  33 import java.util.Comparators;
  34 import java.util.DoubleSummaryStatistics;
  35 import java.util.EnumSet;
  36 import java.util.HashMap;
  37 import java.util.HashSet;
  38 import java.util.IntSummaryStatistics;
  39 import java.util.Iterator;
  40 import java.util.List;
  41 import java.util.LongSummaryStatistics;
  42 import java.util.Map;
  43 import java.util.NoSuchElementException;
  44 import java.util.Objects;
  45 import java.util.Set;
  46 import java.util.StringJoiner;
  47 import java.util.concurrent.ConcurrentHashMap;
  48 import java.util.concurrent.ConcurrentMap;
  49 import java.util.function.BiFunction;
  50 import java.util.function.BinaryOperator;
  51 import java.util.function.Function;
  52 import java.util.function.Predicate;
  53 import java.util.function.Supplier;


  61  * elements according to various criteria, etc.
  62  *
  63  * <p>The following are examples of using the predefined {@code Collector}
  64  * implementations in {@link Collectors} with the {@code Stream} API to perform
  65  * mutable reduction tasks:
  66  *
  67  * <pre>{@code
  68  *     // Accumulate elements into a List
  69  *     List<Person> list = people.collect(Collectors.toList());
  70  *
  71  *     // Accumulate elements into a TreeSet
  72  *     List<Person> list = people.collect(Collectors.toCollection(TreeSet::new));
  73  *
  74  *     // Convert elements to strings and concatenate them, separated by commas
  75  *     String joined = stream.map(Object::toString)
  76  *                           .collect(Collectors.toStringJoiner(", "))
  77  *                           .toString();
  78  *
  79  *     // Find highest-paid employee
  80  *     Employee highestPaid = employees.stream()
  81  *                                     .collect(Collectors.maxBy(Comparators.comparing(Employee::getSalary)));
  82  *
  83  *     // Group employees by department
  84  *     Map<Department, List<Employee>> byDept
  85  *         = employees.stream()
  86  *                    .collect(Collectors.groupingBy(Employee::getDepartment));
  87  *
  88  *     // Find highest-paid employee by department
  89  *     Map<Department, Employee> highestPaidByDept
  90  *         = employees.stream()
  91  *                    .collect(Collectors.groupingBy(Employee::getDepartment,
  92  *                                                   Collectors.maxBy(Comparators.comparing(Employee::getSalary))));
  93  *
  94  *     // Partition students into passing and failing
  95  *     Map<Boolean, List<Student>> passingFailing =
  96  *         students.stream()
  97  *                 .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD);
  98  *
  99  * }</pre>
 100  *
 101  * TODO explanation of parallel collection
 102  *
 103  * @since 1.8
 104  */
 105 public final class Collectors {
 106 
 107     private static final Set<Collector.Characteristics> CH_CONCURRENT
 108             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
 109                                                      Collector.Characteristics.STRICTLY_MUTATIVE,
 110                                                      Collector.Characteristics.UNORDERED));
 111     private static final Set<Collector.Characteristics> CH_STRICT
 112             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.STRICTLY_MUTATIVE));


 387      * This produces a result equivalent to:
 388      * <pre>{@code
 389      *     reducing(0L, e -> 1L, Long::sum)
 390      * }</pre>
 391      *
 392      * @param <T> the type of the input elements
 393      * @return a {@code Collector} that counts the input elements
 394      */
 395     public static <T> Collector<T, Long>
 396     counting() {
 397         return reducing(0L, e -> 1L, Long::sum);
 398     }
 399 
 400     /**
 401      * Returns a {@code Collector<T, T>} that produces the minimal element
 402      * according to a given {@code Comparator}.
 403      *
 404      * @implSpec
 405      * This produces a result equivalent to:
 406      * <pre>{@code
 407      *     reducing(Comparators.lesserOf(comparator))
 408      * }</pre>
 409      *
 410      * @param <T> the type of the input elements
 411      * @param comparator a {@code Comparator} for comparing elements
 412      * @return a {@code Collector} that produces the minimal value
 413      */
 414     public static <T> Collector<T, T>
 415     minBy(Comparator<? super T> comparator) {
 416         return reducing(Comparators.lesserOf(comparator));
 417     }
 418 
 419     /**
 420      * Returns a {@code Collector<T, T>} that produces the maximal element
 421      * according to a given {@code Comparator}.
 422      *
 423      * @implSpec
 424      * This produces a result equivalent to:
 425      * <pre>{@code
 426      *     reducing(Comparators.greaterOf(comparator))
 427      * }</pre>
 428      *
 429      * @param <T> the type of the input elements
 430      * @param comparator a {@code Comparator} for comparing elements
 431      * @return a {@code Collector} that produces the maximal value
 432      */
 433     public static <T> Collector<T, T>
 434     maxBy(Comparator<? super T> comparator) {
 435         return reducing(Comparators.greaterOf(comparator));
 436     }
 437 
 438     /**
 439      * Returns a {@code Collector<T, Long>} that produces the sum of a
 440      * long-valued function applied to the input element.
 441      *
 442      * @implSpec
 443      * This produces a result equivalent to:
 444      * <pre>{@code
 445      *     reducing(0L, mapper, Long::sum)
 446      * }</pre>
 447      *
 448      * @param <T> the type of the input elements
 449      * @param mapper a function extracting the property to be summed
 450      * @return a {@code Collector} that produces the sum of a derived property
 451      */
 452     public static <T> Collector<T, Long>
 453     sumBy(Function<? super T, Long> mapper) {
 454         return reducing(0L, mapper, Long::sum);
 455     }


 474      * @see #reducing(Object, Function, BinaryOperator)
 475      */
 476     public static <T> Collector<T, T>
 477     reducing(T identity, BinaryOperator<T> op) {
 478         return new CollectorImpl<>(() -> identity, (r, t) -> (r == null ? t : op.apply(r, t)), op);
 479     }
 480 
 481     /**
 482      * Returns a {@code Collector<T,T>} which performs a reduction of its
 483      * input elements under a specified {@code BinaryOperator}.
 484      *
 485      * @apiNote
 486      * The {@code reducing()} collectors are most useful when used in a
 487      * multi-level reduction, downstream of {@code groupingBy} or
 488      * {@code partitioningBy}.  To perform a simple reduction on a stream,
 489      * use {@link Stream#reduce(BinaryOperator)} instead.
 490      *
 491      * <p>For example, given a stream of {@code Person}, to calculate tallest
 492      * person in each city:
 493      * <pre>{@code
 494      *     Comparator<Person> byHeight = Comparators.comparing(Person::getHeight);
 495      *     BinaryOperator<Person> tallerOf = Comparators.greaterOf(byHeight);
 496      *     Map<City, Person> tallestByCity
 497      *         = people.stream().collect(groupingBy(Person::getCity, reducing(tallerOf)));
 498      * }</pre>
 499      *
 500      * @implSpec
 501      * The default implementation is equivalent to:
 502      * <pre>{@code
 503      *     reducing(null, op);
 504      * }</pre>
 505      *
 506      * @param <T> element type for the input and output of the reduction
 507      * @param op a {@code BinaryOperator<T>} used to reduce the input elements
 508      * @return a {@code Collector} which implements the reduction operation
 509      *
 510      * @see #reducing(Object, BinaryOperator)
 511      * @see #reducing(Object, Function, BinaryOperator)
 512      */
 513     public static <T> Collector<T, T>
 514     reducing(BinaryOperator<T> op) {
 515         return reducing(null, op);
 516     }
 517 
 518     /**
 519      * Returns a {@code Collector<T,U>} which performs a reduction of its
 520      * input elements under a specified mapping function and
 521      * {@code BinaryOperator}. This is a generalization of
 522      * {@link #reducing(Object, BinaryOperator)} which allows a transformation
 523      * of the elements before reduction.
 524      *
 525      * @apiNote
 526      * The {@code reducing()} collectors are most useful when used in a
 527      * multi-level reduction, downstream of {@code groupingBy} or
 528      * {@code partitioningBy}.  To perform a simple reduction on a stream,
 529      * use {@link Stream#reduce(BinaryOperator)} instead.
 530      *
 531      * <p>For example, given a stream of {@code Person}, to calculate the longest
 532      * last name of residents in each city:
 533      * <pre>{@code
 534      *     Comparator<String> byLength = Comparators.comparing(String::length);
 535      *     BinaryOperator<String> longerOf = Comparators.greaterOf(byLength);
 536      *     Map<City, String> longestLastNameByCity
 537      *         = people.stream().collect(groupingBy(Person::getCity,
 538      *                                              reducing(Person::getLastName, longerOf)));
 539      * }</pre>
 540      *
 541      * @param <T> the type of the input elements
 542      * @param <U> the type of the mapped values
 543      * @param identity the identity value for the reduction (also, the value
 544      *                 that is returned when there are no input elements)
 545      * @param mapper a mapping function to apply to each input value
 546      * @param op a {@code BinaryOperator<U>} used to reduce the mapped values
 547      * @return a {@code Collector} implementing the map-reduce operation
 548      *
 549      * @see #reducing(Object, BinaryOperator)
 550      * @see #reducing(BinaryOperator)
 551      */
 552     public static <T, U>
 553     Collector<T, U> reducing(U identity,
 554                              Function<? super T, ? extends U> mapper,
 555                              BinaryOperator<U> op) {




  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package java.util.stream;
  26 
  27 import java.util.AbstractMap;
  28 import java.util.AbstractSet;
  29 import java.util.ArrayList;
  30 import java.util.Collection;
  31 import java.util.Collections;
  32 import java.util.Comparator;

  33 import java.util.DoubleSummaryStatistics;
  34 import java.util.EnumSet;
  35 import java.util.HashMap;
  36 import java.util.HashSet;
  37 import java.util.IntSummaryStatistics;
  38 import java.util.Iterator;
  39 import java.util.List;
  40 import java.util.LongSummaryStatistics;
  41 import java.util.Map;
  42 import java.util.NoSuchElementException;
  43 import java.util.Objects;
  44 import java.util.Set;
  45 import java.util.StringJoiner;
  46 import java.util.concurrent.ConcurrentHashMap;
  47 import java.util.concurrent.ConcurrentMap;
  48 import java.util.function.BiFunction;
  49 import java.util.function.BinaryOperator;
  50 import java.util.function.Function;
  51 import java.util.function.Predicate;
  52 import java.util.function.Supplier;


  60  * elements according to various criteria, etc.
  61  *
  62  * <p>The following are examples of using the predefined {@code Collector}
  63  * implementations in {@link Collectors} with the {@code Stream} API to perform
  64  * mutable reduction tasks:
  65  *
  66  * <pre>{@code
  67  *     // Accumulate elements into a List
  68  *     List<Person> list = people.collect(Collectors.toList());
  69  *
  70  *     // Accumulate elements into a TreeSet
  71  *     List<Person> list = people.collect(Collectors.toCollection(TreeSet::new));
  72  *
  73  *     // Convert elements to strings and concatenate them, separated by commas
  74  *     String joined = stream.map(Object::toString)
  75  *                           .collect(Collectors.toStringJoiner(", "))
  76  *                           .toString();
  77  *
  78  *     // Find highest-paid employee
  79  *     Employee highestPaid = employees.stream()
  80  *                                     .collect(Collectors.maxBy(Comparator.comparing(Employee::getSalary)));
  81  *
  82  *     // Group employees by department
  83  *     Map<Department, List<Employee>> byDept
  84  *         = employees.stream()
  85  *                    .collect(Collectors.groupingBy(Employee::getDepartment));
  86  *
  87  *     // Find highest-paid employee by department
  88  *     Map<Department, Employee> highestPaidByDept
  89  *         = employees.stream()
  90  *                    .collect(Collectors.groupingBy(Employee::getDepartment,
  91  *                                                   Collectors.maxBy(Comparator.comparing(Employee::getSalary))));
  92  *
  93  *     // Partition students into passing and failing
  94  *     Map<Boolean, List<Student>> passingFailing =
  95  *         students.stream()
  96  *                 .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD);
  97  *
  98  * }</pre>
  99  *
 100  * TODO explanation of parallel collection
 101  *
 102  * @since 1.8
 103  */
 104 public final class Collectors {
 105 
 106     private static final Set<Collector.Characteristics> CH_CONCURRENT
 107             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
 108                                                      Collector.Characteristics.STRICTLY_MUTATIVE,
 109                                                      Collector.Characteristics.UNORDERED));
 110     private static final Set<Collector.Characteristics> CH_STRICT
 111             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.STRICTLY_MUTATIVE));


 386      * This produces a result equivalent to:
 387      * <pre>{@code
 388      *     reducing(0L, e -> 1L, Long::sum)
 389      * }</pre>
 390      *
 391      * @param <T> the type of the input elements
 392      * @return a {@code Collector} that counts the input elements
 393      */
 394     public static <T> Collector<T, Long>
 395     counting() {
 396         return reducing(0L, e -> 1L, Long::sum);
 397     }
 398 
 399     /**
 400      * Returns a {@code Collector<T, T>} that produces the minimal element
 401      * according to a given {@code Comparator}.
 402      *
 403      * @implSpec
 404      * This produces a result equivalent to:
 405      * <pre>{@code
 406      *     reducing(BinaryOperator.minBy(comparator))
 407      * }</pre>
 408      *
 409      * @param <T> the type of the input elements
 410      * @param comparator a {@code Comparator} for comparing elements
 411      * @return a {@code Collector} that produces the minimal value
 412      */
 413     public static <T> Collector<T, T>
 414     minBy(Comparator<? super T> comparator) {
 415         return reducing(BinaryOperator.minBy(comparator));
 416     }
 417 
 418     /**
 419      * Returns a {@code Collector<T, T>} that produces the maximal element
 420      * according to a given {@code Comparator}.
 421      *
 422      * @implSpec
 423      * This produces a result equivalent to:
 424      * <pre>{@code
 425      *     reducing(BinaryOperator.maxBy(comparator))
 426      * }</pre>
 427      *
 428      * @param <T> the type of the input elements
 429      * @param comparator a {@code Comparator} for comparing elements
 430      * @return a {@code Collector} that produces the maximal value
 431      */
 432     public static <T> Collector<T, T>
 433     maxBy(Comparator<? super T> comparator) {
 434         return reducing(BinaryOperator.maxBy(comparator));
 435     }
 436 
 437     /**
 438      * Returns a {@code Collector<T, Long>} that produces the sum of a
 439      * long-valued function applied to the input element.
 440      *
 441      * @implSpec
 442      * This produces a result equivalent to:
 443      * <pre>{@code
 444      *     reducing(0L, mapper, Long::sum)
 445      * }</pre>
 446      *
 447      * @param <T> the type of the input elements
 448      * @param mapper a function extracting the property to be summed
 449      * @return a {@code Collector} that produces the sum of a derived property
 450      */
 451     public static <T> Collector<T, Long>
 452     sumBy(Function<? super T, Long> mapper) {
 453         return reducing(0L, mapper, Long::sum);
 454     }


 473      * @see #reducing(Object, Function, BinaryOperator)
 474      */
 475     public static <T> Collector<T, T>
 476     reducing(T identity, BinaryOperator<T> op) {
 477         return new CollectorImpl<>(() -> identity, (r, t) -> (r == null ? t : op.apply(r, t)), op);
 478     }
 479 
 480     /**
 481      * Returns a {@code Collector<T,T>} which performs a reduction of its
 482      * input elements under a specified {@code BinaryOperator}.
 483      *
 484      * @apiNote
 485      * The {@code reducing()} collectors are most useful when used in a
 486      * multi-level reduction, downstream of {@code groupingBy} or
 487      * {@code partitioningBy}.  To perform a simple reduction on a stream,
 488      * use {@link Stream#reduce(BinaryOperator)} instead.
 489      *
 490      * <p>For example, given a stream of {@code Person}, to calculate tallest
 491      * person in each city:
 492      * <pre>{@code
 493      *     Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
 494      *     BinaryOperator<Person> tallerOf = BinaryOperator.greaterOf(byHeight);
 495      *     Map<City, Person> tallestByCity
 496      *         = people.stream().collect(groupingBy(Person::getCity, reducing(tallerOf)));
 497      * }</pre>
 498      *
 499      * @implSpec
 500      * The default implementation is equivalent to:
 501      * <pre>{@code
 502      *     reducing(null, op);
 503      * }</pre>
 504      *
 505      * @param <T> element type for the input and output of the reduction
 506      * @param op a {@code BinaryOperator<T>} used to reduce the input elements
 507      * @return a {@code Collector} which implements the reduction operation
 508      *
 509      * @see #reducing(Object, BinaryOperator)
 510      * @see #reducing(Object, Function, BinaryOperator)
 511      */
 512     public static <T> Collector<T, T>
 513     reducing(BinaryOperator<T> op) {
 514         return reducing(null, op);
 515     }
 516 
 517     /**
 518      * Returns a {@code Collector<T,U>} which performs a reduction of its
 519      * input elements under a specified mapping function and
 520      * {@code BinaryOperator}. This is a generalization of
 521      * {@link #reducing(Object, BinaryOperator)} which allows a transformation
 522      * of the elements before reduction.
 523      *
 524      * @apiNote
 525      * The {@code reducing()} collectors are most useful when used in a
 526      * multi-level reduction, downstream of {@code groupingBy} or
 527      * {@code partitioningBy}.  To perform a simple reduction on a stream,
 528      * use {@link Stream#reduce(BinaryOperator)} instead.
 529      *
 530      * <p>For example, given a stream of {@code Person}, to calculate the longest
 531      * last name of residents in each city:
 532      * <pre>{@code
 533      *     Comparator<String> byLength = Comparator.comparing(String::length);
 534      *     BinaryOperator<String> longerOf = BinaryOperator.greaterOf(byLength);
 535      *     Map<City, String> longestLastNameByCity
 536      *         = people.stream().collect(groupingBy(Person::getCity,
 537      *                                              reducing(Person::getLastName, longerOf)));
 538      * }</pre>
 539      *
 540      * @param <T> the type of the input elements
 541      * @param <U> the type of the mapped values
 542      * @param identity the identity value for the reduction (also, the value
 543      *                 that is returned when there are no input elements)
 544      * @param mapper a mapping function to apply to each input value
 545      * @param op a {@code BinaryOperator<U>} used to reduce the mapped values
 546      * @return a {@code Collector} implementing the map-reduce operation
 547      *
 548      * @see #reducing(Object, BinaryOperator)
 549      * @see #reducing(BinaryOperator)
 550      */
 551     public static <T, U>
 552     Collector<T, U> reducing(U identity,
 553                              Function<? super T, ? extends U> mapper,
 554                              BinaryOperator<U> op) {