       1 /*
       2  * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
       3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       4  *
       5  * This code is free software; you can redistribute it and/or modify it
       6  * under the terms of the GNU General Public License version 2 only, as
       7  * published by the Free Software Foundation.  Oracle designates this
       8  * particular file as subject to the "Classpath" exception as provided
       9  * by Oracle in the LICENSE file that accompanied this code.
      10  *
      11  * This code is distributed in the hope that it will be useful, but WITHOUT
      12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      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.Objects;
      43 import java.util.Optional;
      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.BiConsumer;
      49 import java.util.function.BiFunction;
      50 import java.util.function.BinaryOperator;
      51 import java.util.function.Consumer;
      52 import java.util.function.Function;
      53 import java.util.function.Predicate;
      54 import java.util.function.Supplier;
      55 import java.util.function.ToDoubleFunction;
      56 import java.util.function.ToIntFunction;
      57 import java.util.function.ToLongFunction;
      58
      59 /**
      60  * Implementations of {@link Collector} that implement various useful reduction
      61  * operations, such as accumulating elements into collections, summarizing
      62  * elements according to various criteria, etc.
      63  *
      64  * <p>The following are examples of using the predefined collectors to perform
      65  * common mutable reduction tasks:
      66  *
      67  * <pre>{@code
      68  * // Accumulate names into a List
      69  * List<String> list = people.stream()
      70  *   .map(Person::getName)
      71  *   .collect(Collectors.toList());
      72  *
      73  * // Accumulate names into a TreeSet
      74  * Set<String> set = people.stream()
      75  *   .map(Person::getName)
      76  *   .collect(Collectors.toCollection(TreeSet::new));
      77  *
      78  * // Convert elements to strings and concatenate them, separated by commas
      79  * String joined = things.stream()
      80  *   .map(Object::toString)
      81  *   .collect(Collectors.joining(", "));
      82  *
      83  * // Compute sum of salaries of employee
      84  * int total = employees.stream()
      85  *   .collect(Collectors.summingInt(Employee::getSalary));
      86  *
      87  * // Group employees by department
      88  * Map<Department, List<Employee>> byDept = employees.stream()
      89  *   .collect(Collectors.groupingBy(Employee::getDepartment));
      90  *
      91  * // Compute sum of salaries by department
      92  * Map<Department, Integer> totalByDept = employees.stream()
      93  *   .collect(Collectors.groupingBy(Employee::getDepartment,
      94  *                                  Collectors.summingInt(Employee::getSalary)));
      95  *
      96  * // Partition students into passing and failing
      97  * Map<Boolean, List<Student>> passingFailing = students.stream()
      98  *   .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
      99  *
     100  * }</pre>
     101  *
     102  * @since 1.8
     103  */
     104 public final class Collectors {
     105
     106     static final Set<Collector.Characteristics> CH_CONCURRENT_ID
     107             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
     108                                                      Collector.Characteristics.UNORDERED,
     109                                                      Collector.Characteristics.IDENTITY_FINISH));
     110     static final Set<Collector.Characteristics> CH_CONCURRENT_NOID
     111             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
     112                                                      Collector.Characteristics.UNORDERED));
     113     static final Set<Collector.Characteristics> CH_ID
     114             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
     115     static final Set<Collector.Characteristics> CH_UNORDERED_ID
     116             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
     117                                                      Collector.Characteristics.IDENTITY_FINISH));
     118     static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
     119     static final Set<Collector.Characteristics> CH_UNORDERED_NOID
     120             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED));
     121
     122     private Collectors() { }
     123
     124     /**
     125      * Construct an {@code IllegalStateException} with appropriate message.
     126      *
     127      * @param k the duplicate key
     128      * @param u 1st value to be accumulated/merged
     129      * @param v 2nd value to be accumulated/merged
     130      */
     131     private static IllegalStateException duplicateKeyException(
     132             Object k, Object u, Object v) {
     133         return new IllegalStateException(String.format(
     134             "Duplicate key %s (attempted merging values %s and %s)",
     135             k, u, v));
     136     }
     137
     138     /**
     139      * {@code BinaryOperator<Map>} that merges the contents of its right
     140      * argument into its left argument, throwing {@code IllegalStateException}
     141      * if duplicate keys are encountered.
     142      *
     143      * @param <K> type of the map keys
     144      * @param <V> type of the map values
     145      * @param <M> type of the map
     146      * @return a merge function for two maps
     147      */
     148     private static <K, V, M extends Map<K,V>>
     149     BinaryOperator<M> uniqKeysMapMerger() {
     150         return (m1, m2) -> {
     151             for (Map.Entry<K,V> e : m2.entrySet()) {
     152                 K k = e.getKey();
     153                 V v = Objects.requireNonNull(e.getValue());
     154                 V u = m1.putIfAbsent(k, v);
     155                 if (u != null) throw duplicateKeyException(k, u, v);
     156             }
     157             return m1;
     158         };
     159     }
     160
     161     /**
     162      * {@code BiConsumer<Map, T>} that accumulates (key, value) pairs
     163      * extracted from elements into the map, throwing {@code IllegalStateException}
     164      * if duplicate keys are encountered.
     165      *
     166      * @param keyMapper a function that maps an element into a key
     167      * @param valueMapper a function that maps an element into a value
     168      * @param <T> type of elements
     169      * @param <K> type of map keys
     170      * @param <V> type of map values
     171      * @return an accumulating consumer
     172      */
     173     private static <T, K, V>
     174     BiConsumer<Map<K, V>, T> uniqKeysMapAccumulator(Function<? super T, ? extends K> keyMapper,
     175                                                     Function<? super T, ? extends V> valueMapper) {
     176         return (map, element) -> {
     177             K k = keyMapper.apply(element);
     178             V v = Objects.requireNonNull(valueMapper.apply(element));
     179             V u = map.putIfAbsent(k, v);
     180             if (u != null) throw duplicateKeyException(k, u, v);
     181         };
     182     }
     183
     184     @SuppressWarnings("unchecked")
     185     private static <I, R> Function<I, R> castingIdentity() {
     186         return i -> (R) i;
     187     }
     188
     189     /**
     190      * Simple implementation class for {@code Collector}.
     191      *
     192      * @param <T> the type of elements to be collected
     193      * @param <R> the type of the result
     194      */
     195     static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
     196         private final Supplier<A> supplier;
     197         private final BiConsumer<A, T> accumulator;
     198         private final BinaryOperator<A> combiner;
     199         private final Function<A, R> finisher;
     200         private final Set<Characteristics> characteristics;
     201
     202         CollectorImpl(Supplier<A> supplier,
     203                       BiConsumer<A, T> accumulator,
     204                       BinaryOperator<A> combiner,
     205                       Function<A,R> finisher,
     206                       Set<Characteristics> characteristics) {
     207             this.supplier = supplier;
     208             this.accumulator = accumulator;
     209             this.combiner = combiner;
     210             this.finisher = finisher;
     211             this.characteristics = characteristics;
     212         }
     213
     214         CollectorImpl(Supplier<A> supplier,
     215                       BiConsumer<A, T> accumulator,
     216                       BinaryOperator<A> combiner,
     217                       Set<Characteristics> characteristics) {
     218             this(supplier, accumulator, combiner, castingIdentity(), characteristics);
     219         }
     220
     221         @Override
     222         public BiConsumer<A, T> accumulator() {
     223             return accumulator;
     224         }
     225
     226         @Override
     227         public Supplier<A> supplier() {
     228             return supplier;
     229         }
     230
     231         @Override
     232         public BinaryOperator<A> combiner() {
     233             return combiner;
     234         }
     235
     236         @Override
     237         public Function<A, R> finisher() {
     238             return finisher;
     239         }
     240
     241         @Override
     242         public Set<Characteristics> characteristics() {
     243             return characteristics;
     244         }
     245     }
     246
     247     /**
     248      * Returns a {@code Collector} that accumulates the input elements into a
     249      * new {@code Collection}, in encounter order.  The {@code Collection} is
     250      * created by the provided factory.
     251      *
     252      * @param <T> the type of the input elements
     253      * @param <C> the type of the resulting {@code Collection}
     254      * @param collectionFactory a supplier providing a new empty {@code Collection}
     255      *                          into which the results will be inserted
     256      * @return a {@code Collector} which collects all the input elements into a
     257      * {@code Collection}, in encounter order
     258      */
     259     public static <T, C extends Collection<T>>
     260     Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
     261         return new CollectorImpl<>(collectionFactory, Collection<T>::add,
     262                                    (r1, r2) -> { r1.addAll(r2); return r1; },
     263                                    CH_ID);
     264     }
     265
     266     /**
     267      * Returns a {@code Collector} that accumulates the input elements into a
     268      * new {@code List}. There are no guarantees on the type, mutability,
     269      * serializability, or thread-safety of the {@code List} returned; if more
     270      * control over the returned {@code List} is required, use {@link #toCollection(Supplier)}.
     271      *
     272      * @param <T> the type of the input elements
     273      * @return a {@code Collector} which collects all the input elements into a
     274      * {@code List}, in encounter order
     275      */
     276     public static <T>
     277     Collector<T, ?, List<T>> toList() {
     278         return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
     279                                    (left, right) -> { left.addAll(right); return left; },
     280                                    CH_ID);
     281     }
     282
     283     /**
     284      * Returns a {@code Collector} that accumulates the input elements into an
     285      * <a href="../List.html#unmodifiable">unmodifiable List</a> in encounter
     286      * order. The returned Collector disallows null values and will throw
     287      * {@code NullPointerException} if it is presented with a null value.
     288      *
     289      * @param <T> the type of the input elements
     290      * @return a {@code Collector} which collects all the input elements into a
     291      * {@code List}, in encounter order
     292      * @since 10
     293      */
     294     @SuppressWarnings("unchecked")
     295     public static <T>
     296     Collector<T, ?, List<T>> toUnmodifiableList() {
     297         return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
     298                                    (left, right) -> { left.addAll(right); return left; },
     299                                    list -> (List<T>)List.of(list.toArray()),
     300                                    CH_NOID);
     301     }
     302
     303     /**
     304      * Returns a {@code Collector} that accumulates the input elements into a
     305      * new {@code Set}. There are no guarantees on the type, mutability,
     306      * serializability, or thread-safety of the {@code Set} returned; if more
     307      * control over the returned {@code Set} is required, use
     308      * {@link #toCollection(Supplier)}.
     309      *
     310      * <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
     311      * Collector.
     312      *
     313      * @param <T> the type of the input elements
     314      * @return a {@code Collector} which collects all the input elements into a
     315      * {@code Set}
     316      */
     317     public static <T>
     318     Collector<T, ?, Set<T>> toSet() {
     319         return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
     320                                    (left, right) -> {
     321                                        if (left.size() < right.size()) {
     322                                            right.addAll(left); return right;
     323                                        } else {
     324                                            left.addAll(right); return left;
     325                                        }
     326                                    },
     327                                    CH_UNORDERED_ID);
     328     }
     329
     330     /**
     331      * Returns a {@code Collector} that accumulates the input elements into an
     332      * <a href="../Set.html#unmodifiable">unmodifiable Set</a>. The returned
     333      * Collector disallows null values and will throw {@code NullPointerException}
     334      * if it is presented with a null value. If the input contains duplicate elements,
     335      * an arbitrary element of the duplicates is preserved.
     336      *
     337      * <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
     338      * Collector.
     339      *
     340      * @param <T> the type of the input elements
     341      * @return a {@code Collector} which collects all the input elements into a
     342      * {@code Set}
     343      * @since 10
     344      */
     345     @SuppressWarnings("unchecked")
     346     public static <T>
     347     Collector<T, ?, Set<T>> toUnmodifiableSet() {
     348         return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
     349                                    (left, right) -> {
     350                                        if (left.size() < right.size()) {
     351                                            right.addAll(left); return right;
     352                                        } else {
     353                                            left.addAll(right); return left;
     354                                        }
     355                                    },
     356                                    set -> (Set<T>)Set.of(set.toArray()),
     357                                    CH_UNORDERED_NOID);
     358     }
     359
     360     /**
     361      * Returns a {@code Collector} that concatenates the input elements into a
     362      * {@code String}, in encounter order.
     363      *
     364      * @return a {@code Collector} that concatenates the input elements into a
     365      * {@code String}, in encounter order
     366      */
     367     public static Collector<CharSequence, ?, String> joining() {
     368         return new CollectorImpl<CharSequence, StringBuilder, String>(
     369                 StringBuilder::new, StringBuilder::append,
     370                 (r1, r2) -> { r1.append(r2); return r1; },
     371                 StringBuilder::toString, CH_NOID);
     372     }
     373
     374     /**
     375      * Returns a {@code Collector} that concatenates the input elements,
     376      * separated by the specified delimiter, in encounter order.
     377      *
     378      * @param delimiter the delimiter to be used between each element
     379      * @return A {@code Collector} which concatenates CharSequence elements,
     380      * separated by the specified delimiter, in encounter order
     381      */
     382     public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {
     383         return joining(delimiter, "", "");
     384     }
     385
     386     /**
     387      * Returns a {@code Collector} that concatenates the input elements,
     388      * separated by the specified delimiter, with the specified prefix and
     389      * suffix, in encounter order.
     390      *
     391      * @param delimiter the delimiter to be used between each element
     392      * @param  prefix the sequence of characters to be used at the beginning
     393      *                of the joined result
     394      * @param  suffix the sequence of characters to be used at the end
     395      *                of the joined result
     396      * @return A {@code Collector} which concatenates CharSequence elements,
     397      * separated by the specified delimiter, in encounter order
     398      */
     399     public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
     400                                                              CharSequence prefix,
     401                                                              CharSequence suffix) {
     402         return new CollectorImpl<>(
     403                 () -> new StringJoiner(delimiter, prefix, suffix),
     404                 StringJoiner::add, StringJoiner::merge,
     405                 StringJoiner::toString, CH_NOID);
     406     }
     407
     408     /**
     409      * {@code BinaryOperator<Map>} that merges the contents of its right
     410      * argument into its left argument, using the provided merge function to
     411      * handle duplicate keys.
     412      *
     413      * @param <K> type of the map keys
     414      * @param <V> type of the map values
     415      * @param <M> type of the map
     416      * @param mergeFunction A merge function suitable for
     417      * {@link Map#merge(Object, Object, BiFunction) Map.merge()}
     418      * @return a merge function for two maps
     419      */
     420     private static <K, V, M extends Map<K,V>>
     421     BinaryOperator<M> mapMerger(BinaryOperator<V> mergeFunction) {
     422         return (m1, m2) -> {
     423             for (Map.Entry<K,V> e : m2.entrySet())
     424                 m1.merge(e.getKey(), e.getValue(), mergeFunction);
     425             return m1;
     426         };
     427     }
     428
     429     /**
     430      * Adapts a {@code Collector} accepting elements of type {@code U} to one
     431      * accepting elements of type {@code T} by applying a mapping function to
     432      * each input element before accumulation.
     433      *
     434      * @apiNote
     435      * The {@code mapping()} collectors are most useful when used in a
     436      * multi-level reduction, such as downstream of a {@code groupingBy} or
     437      * {@code partitioningBy}.  For example, given a stream of
     438      * {@code Person}, to accumulate the set of last names in each city:
     439      * <pre>{@code
     440      * Map<City, Set<String>> lastNamesByCity
     441      *   = people.stream().collect(
     442      *     groupingBy(Person::getCity,
     443      *                mapping(Person::getLastName,
     444      *                        toSet())));
     445      * }</pre>
     446      *
     447      * @param <T> the type of the input elements
     448      * @param <U> type of elements accepted by downstream collector
     449      * @param <A> intermediate accumulation type of the downstream collector
     450      * @param <R> result type of collector
     451      * @param mapper a function to be applied to the input elements
     452      * @param downstream a collector which will accept mapped values
     453      * @return a collector which applies the mapping function to the input
     454      * elements and provides the mapped results to the downstream collector
     455      */
     456     public static <T, U, A, R>
     457     Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
     458                                Collector<? super U, A, R> downstream) {
     459         BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
     460         return new CollectorImpl<>(downstream.supplier(),
     461                                    (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
     462                                    downstream.combiner(), downstream.finisher(),
     463                                    downstream.characteristics());
     464     }
     465
     466     /**
     467      * Adapts a {@code Collector} accepting elements of type {@code U} to one
     468      * accepting elements of type {@code T} by applying a flat mapping function
     469      * to each input element before accumulation.  The flat mapping function
     470      * maps an input element to a {@link Stream stream} covering zero or more
     471      * output elements that are then accumulated downstream.  Each mapped stream
     472      * is {@link java.util.stream.BaseStream#close() closed} after its contents
     473      * have been placed downstream.  (If a mapped stream is {@code null}
     474      * an empty stream is used, instead.)
     475      *
     476      * @apiNote
     477      * The {@code flatMapping()} collectors are most useful when used in a
     478      * multi-level reduction, such as downstream of a {@code groupingBy} or
     479      * {@code partitioningBy}.  For example, given a stream of
     480      * {@code Order}, to accumulate the set of line items for each customer:
     481      * <pre>{@code
     482      * Map<String, Set<LineItem>> itemsByCustomerName
     483      *   = orders.stream().collect(
     484      *     groupingBy(Order::getCustomerName,
     485      *                flatMapping(order -> order.getLineItems().stream(),
     486      *                            toSet())));
     487      * }</pre>
     488      *
     489      * @param <T> the type of the input elements
     490      * @param <U> type of elements accepted by downstream collector
     491      * @param <A> intermediate accumulation type of the downstream collector
     492      * @param <R> result type of collector
     493      * @param mapper a function to be applied to the input elements, which
     494      * returns a stream of results
     495      * @param downstream a collector which will receive the elements of the
     496      * stream returned by mapper
     497      * @return a collector which applies the mapping function to the input
     498      * elements and provides the flat mapped results to the downstream collector
     499      * @since 9
     500      */
     501     public static <T, U, A, R>
     502     Collector<T, ?, R> flatMapping(Function<? super T, ? extends Stream<? extends U>> mapper,
     503                                    Collector<? super U, A, R> downstream) {
     504         BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
     505         return new CollectorImpl<>(downstream.supplier(),
     506                             (r, t) -> {
     507                                 try (Stream<? extends U> result = mapper.apply(t)) {
     508                                     if (result != null)
     509                                         result.sequential().forEach(u -> downstreamAccumulator.accept(r, u));
     510                                 }
     511                             },
     512                             downstream.combiner(), downstream.finisher(),
     513                             downstream.characteristics());
     514     }
     515
     516     /**
     517      * Adapts a {@code Collector} to one accepting elements of the same type
     518      * {@code T} by applying the predicate to each input element and only
     519      * accumulating if the predicate returns {@code true}.
     520      *
     521      * @apiNote
     522      * The {@code filtering()} collectors are most useful when used in a
     523      * multi-level reduction, such as downstream of a {@code groupingBy} or
     524      * {@code partitioningBy}.  For example, given a stream of
     525      * {@code Employee}, to accumulate the employees in each department that have a
     526      * salary above a certain threshold:
     527      * <pre>{@code
     528      * Map<Department, Set<Employee>> wellPaidEmployeesByDepartment
     529      *   = employees.stream().collect(
     530      *     groupingBy(Employee::getDepartment,
     531      *                filtering(e -> e.getSalary() > 2000,
     532      *                          toSet())));
     533      * }</pre>
     534      * A filtering collector differs from a stream's {@code filter()} operation.
     535      * In this example, suppose there are no employees whose salary is above the
     536      * threshold in some department.  Using a filtering collector as shown above
     537      * would result in a mapping from that department to an empty {@code Set}.
     538      * If a stream {@code filter()} operation were done instead, there would be
     539      * no mapping for that department at all.
     540      *
     541      * @param <T> the type of the input elements
     542      * @param <A> intermediate accumulation type of the downstream collector
     543      * @param <R> result type of collector
     544      * @param predicate a predicate to be applied to the input elements
     545      * @param downstream a collector which will accept values that match the
     546      * predicate
     547      * @return a collector which applies the predicate to the input elements
     548      * and provides matching elements to the downstream collector
     549      * @since 9
     550      */
     551     public static <T, A, R>
     552     Collector<T, ?, R> filtering(Predicate<? super T> predicate,
     553                                  Collector<? super T, A, R> downstream) {
     554         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
     555         return new CollectorImpl<>(downstream.supplier(),
     556                                    (r, t) -> {
     557                                        if (predicate.test(t)) {
     558                                            downstreamAccumulator.accept(r, t);
     559                                        }
     560                                    },
     561                                    downstream.combiner(), downstream.finisher(),
     562                                    downstream.characteristics());
     563     }
     564
     565     /**
     566      * Adapts a {@code Collector} to perform an additional finishing
     567      * transformation.  For example, one could adapt the {@link #toList()}
     568      * collector to always produce an immutable list with:
     569      * <pre>{@code
     570      * List<String> list = people.stream().collect(
     571      *   collectingAndThen(toList(),
     572      *                     Collections::unmodifiableList));
     573      * }</pre>
     574      *
     575      * @param <T> the type of the input elements
     576      * @param <A> intermediate accumulation type of the downstream collector
     577      * @param <R> result type of the downstream collector
     578      * @param <RR> result type of the resulting collector
     579      * @param downstream a collector
     580      * @param finisher a function to be applied to the final result of the downstream collector
     581      * @return a collector which performs the action of the downstream collector,
     582      * followed by an additional finishing step
     583      */
     584     public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
     585                                                                 Function<R,RR> finisher) {
     586         Set<Collector.Characteristics> characteristics = downstream.characteristics();
     587         if (characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) {
     588             if (characteristics.size() == 1)
     589                 characteristics = Collectors.CH_NOID;
     590             else {
     591                 characteristics = EnumSet.copyOf(characteristics);
     592                 characteristics.remove(Collector.Characteristics.IDENTITY_FINISH);
     593                 characteristics = Collections.unmodifiableSet(characteristics);
     594             }
     595         }
     596         return new CollectorImpl<>(downstream.supplier(),
     597                                    downstream.accumulator(),
     598                                    downstream.combiner(),
     599                                    downstream.finisher().andThen(finisher),
     600                                    characteristics);
     601     }
     602
     603     /**
     604      * Returns a {@code Collector} accepting elements of type {@code T} that
     605      * counts the number of input elements.  If no elements are present, the
     606      * result is 0.
     607      *
     608      * @implSpec
     609      * This produces a result equivalent to:
     610      * <pre>{@code
     611      *     reducing(0L, e -> 1L, Long::sum)
     612      * }</pre>
     613      *
     614      * @param <T> the type of the input elements
     615      * @return a {@code Collector} that counts the input elements
     616      */
     617     public static <T> Collector<T, ?, Long>
     618     counting() {
     619         return summingLong(e -> 1L);
     620     }
     621
     622     /**
     623      * Returns a {@code Collector} that produces the minimal element according
     624      * to a given {@code Comparator}, described as an {@code Optional<T>}.
     625      *
     626      * @implSpec
     627      * This produces a result equivalent to:
     628      * <pre>{@code
     629      *     reducing(BinaryOperator.minBy(comparator))
     630      * }</pre>
     631      *
     632      * @param <T> the type of the input elements
     633      * @param comparator a {@code Comparator} for comparing elements
     634      * @return a {@code Collector} that produces the minimal value
     635      */
     636     public static <T> Collector<T, ?, Optional<T>>
     637     minBy(Comparator<? super T> comparator) {
     638         return reducing(BinaryOperator.minBy(comparator));
     639     }
     640
     641     /**
     642      * Returns a {@code Collector} that produces the maximal element according
     643      * to a given {@code Comparator}, described as an {@code Optional<T>}.
     644      *
     645      * @implSpec
     646      * This produces a result equivalent to:
     647      * <pre>{@code
     648      *     reducing(BinaryOperator.maxBy(comparator))
     649      * }</pre>
     650      *
     651      * @param <T> the type of the input elements
     652      * @param comparator a {@code Comparator} for comparing elements
     653      * @return a {@code Collector} that produces the maximal value
     654      */
     655     public static <T> Collector<T, ?, Optional<T>>
     656     maxBy(Comparator<? super T> comparator) {
     657         return reducing(BinaryOperator.maxBy(comparator));
     658     }
     659
     660     /**
     661      * Returns a {@code Collector} that produces the sum of a integer-valued
     662      * function applied to the input elements.  If no elements are present,
     663      * the result is 0.
     664      *
     665      * @param <T> the type of the input elements
     666      * @param mapper a function extracting the property to be summed
     667      * @return a {@code Collector} that produces the sum of a derived property
     668      */
     669     public static <T> Collector<T, ?, Integer>
     670     summingInt(ToIntFunction<? super T> mapper) {
     671         return new CollectorImpl<>(
     672                 () -> new int[1],
     673                 (a, t) -> { a[0] += mapper.applyAsInt(t); },
     674                 (a, b) -> { a[0] += b[0]; return a; },
     675                 a -> a[0], CH_NOID);
     676     }
     677
     678     /**
     679      * Returns a {@code Collector} that produces the sum of a long-valued
     680      * function applied to the input elements.  If no elements are present,
     681      * the result is 0.
     682      *
     683      * @param <T> the type of the input elements
     684      * @param mapper a function extracting the property to be summed
     685      * @return a {@code Collector} that produces the sum of a derived property
     686      */
     687     public static <T> Collector<T, ?, Long>
     688     summingLong(ToLongFunction<? super T> mapper) {
     689         return new CollectorImpl<>(
     690                 () -> new long[1],
     691                 (a, t) -> { a[0] += mapper.applyAsLong(t); },
     692                 (a, b) -> { a[0] += b[0]; return a; },
     693                 a -> a[0], CH_NOID);
     694     }
     695
     696     /**
     697      * Returns a {@code Collector} that produces the sum of a double-valued
     698      * function applied to the input elements.  If no elements are present,
     699      * the result is 0.
     700      *
     701      * <p>The sum returned can vary depending upon the order in which
     702      * values are recorded, due to accumulated rounding error in
     703      * addition of values of differing magnitudes. Values sorted by increasing
     704      * absolute magnitude tend to yield more accurate results.  If any recorded
     705      * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
     706      * sum will be {@code NaN}.
     707      *
     708      * @param <T> the type of the input elements
     709      * @param mapper a function extracting the property to be summed
     710      * @return a {@code Collector} that produces the sum of a derived property
     711      */
     712     public static <T> Collector<T, ?, Double>
     713     summingDouble(ToDoubleFunction<? super T> mapper) {
     714         /*
     715          * In the arrays allocated for the collect operation, index 0
     716          * holds the high-order bits of the running sum, index 1 holds
     717          * the low-order bits of the sum computed via compensated
     718          * summation, and index 2 holds the simple sum used to compute
     719          * the proper result if the stream contains infinite values of
     720          * the same sign.
     721          */
     722         return new CollectorImpl<>(
     723                 () -> new double[3],
     724                 (a, t) -> { double val = mapper.applyAsDouble(t);
     725                             sumWithCompensation(a, val);
     726                             a[2] += val;},
     727                 (a, b) -> { sumWithCompensation(a, b[0]);
     728                             a[2] += b[2];
     729                             return sumWithCompensation(a, b[1]); },
     730                 a -> computeFinalSum(a),
     731                 CH_NOID);
     732     }
     733
     734     /**
     735      * Incorporate a new double value using Kahan summation /
     736      * compensation summation.
     737      *
     738      * High-order bits of the sum are in intermediateSum[0], low-order
     739      * bits of the sum are in intermediateSum[1], any additional
     740      * elements are application-specific.
     741      *
     742      * @param intermediateSum the high-order and low-order words of the intermediate sum
     743      * @param value the name value to be included in the running sum
     744      */
     745     static double[] sumWithCompensation(double[] intermediateSum, double value) {
     746         double tmp = value - intermediateSum[1];
     747         double sum = intermediateSum[0];
     748         double velvel = sum + tmp; // Little wolf of rounding error
     749         intermediateSum[1] = (velvel - sum) - tmp;
     750         intermediateSum[0] = velvel;
     751         return intermediateSum;
     752     }
     753
     754     /**
     755      * If the compensated sum is spuriously NaN from accumulating one
     756      * or more same-signed infinite values, return the
     757      * correctly-signed infinity stored in the simple sum.
     758      */
     759     static double computeFinalSum(double[] summands) {
     760         // Better error bounds to add both terms as the final sum
     761         double tmp = summands[0] + summands[1];
     762         double simpleSum = summands[summands.length - 1];
     763         if (Double.isNaN(tmp) && Double.isInfinite(simpleSum))
     764             return simpleSum;
     765         else
     766             return tmp;
     767     }
     768
     769     /**
     770      * Returns a {@code Collector} that produces the arithmetic mean of an integer-valued
     771      * function applied to the input elements.  If no elements are present,
     772      * the result is 0.
     773      *
     774      * @param <T> the type of the input elements
     775      * @param mapper a function extracting the property to be averaged
     776      * @return a {@code Collector} that produces the arithmetic mean of a
     777      * derived property
     778      */
     779     public static <T> Collector<T, ?, Double>
     780     averagingInt(ToIntFunction<? super T> mapper) {
     781         return new CollectorImpl<>(
     782                 () -> new long[2],
     783                 (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; },
     784                 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
     785                 a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);
     786     }
     787
     788     /**
     789      * Returns a {@code Collector} that produces the arithmetic mean of a long-valued
     790      * function applied to the input elements.  If no elements are present,
     791      * the result is 0.
     792      *
     793      * @param <T> the type of the input elements
     794      * @param mapper a function extracting the property to be averaged
     795      * @return a {@code Collector} that produces the arithmetic mean of a
     796      * derived property
     797      */
     798     public static <T> Collector<T, ?, Double>
     799     averagingLong(ToLongFunction<? super T> mapper) {
     800         return new CollectorImpl<>(
     801                 () -> new long[2],
     802                 (a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; },
     803                 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
     804                 a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);
     805     }
     806
     807     /**
     808      * Returns a {@code Collector} that produces the arithmetic mean of a double-valued
     809      * function applied to the input elements.  If no elements are present,
     810      * the result is 0.
     811      *
     812      * <p>The average returned can vary depending upon the order in which
     813      * values are recorded, due to accumulated rounding error in
     814      * addition of values of differing magnitudes. Values sorted by increasing
     815      * absolute magnitude tend to yield more accurate results.  If any recorded
     816      * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
     817      * average will be {@code NaN}.
     818      *
     819      * @implNote The {@code double} format can represent all
     820      * consecutive integers in the range -2<sup>53</sup> to
     821      * 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup>
     822      * values, the divisor in the average computation will saturate at
     823      * 2<sup>53</sup>, leading to additional numerical errors.
     824      *
     825      * @param <T> the type of the input elements
     826      * @param mapper a function extracting the property to be averaged
     827      * @return a {@code Collector} that produces the arithmetic mean of a
     828      * derived property
     829      */
     830     public static <T> Collector<T, ?, Double>
     831     averagingDouble(ToDoubleFunction<? super T> mapper) {
     832         /*
     833          * In the arrays allocated for the collect operation, index 0
     834          * holds the high-order bits of the running sum, index 1 holds
     835          * the low-order bits of the sum computed via compensated
     836          * summation, and index 2 holds the number of values seen.
     837          */
     838         return new CollectorImpl<>(
     839                 () -> new double[4],
     840                 (a, t) -> { double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2]++; a[3]+= val;},
     841                 (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
     842                 a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
     843                 CH_NOID);
     844     }
     845
     846     /**
     847      * Returns a {@code Collector} which performs a reduction of its
     848      * input elements under a specified {@code BinaryOperator} using the
     849      * provided identity.
     850      *
     851      * @apiNote
     852      * The {@code reducing()} collectors are most useful when used in a
     853      * multi-level reduction, downstream of {@code groupingBy} or
     854      * {@code partitioningBy}.  To perform a simple reduction on a stream,
     855      * use {@link Stream#reduce(Object, BinaryOperator)}} instead.
     856      *
     857      * @param <T> element type for the input and output of the reduction
     858      * @param identity the identity value for the reduction (also, the value
     859      *                 that is returned when there are no input elements)
     860      * @param op a {@code BinaryOperator<T>} used to reduce the input elements
     861      * @return a {@code Collector} which implements the reduction operation
     862      *
     863      * @see #reducing(BinaryOperator)
     864      * @see #reducing(Object, Function, BinaryOperator)
     865      */
     866     public static <T> Collector<T, ?, T>
     867     reducing(T identity, BinaryOperator<T> op) {
     868         return new CollectorImpl<>(
     869                 boxSupplier(identity),
     870                 (a, t) -> { a[0] = op.apply(a[0], t); },
     871                 (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
     872                 a -> a[0],
     873                 CH_NOID);
     874     }
     875
     876     @SuppressWarnings("unchecked")
     877     private static <T> Supplier<T[]> boxSupplier(T identity) {
     878         return () -> (T[]) new Object[] { identity };
     879     }
     880
     881     /**
     882      * Returns a {@code Collector} which performs a reduction of its
     883      * input elements under a specified {@code BinaryOperator}.  The result
     884      * is described as an {@code Optional<T>}.
     885      *
     886      * @apiNote
     887      * The {@code reducing()} collectors are most useful when used in a
     888      * multi-level reduction, downstream of {@code groupingBy} or
     889      * {@code partitioningBy}.  To perform a simple reduction on a stream,
     890      * use {@link Stream#reduce(BinaryOperator)} instead.
     891      *
     892      * <p>For example, given a stream of {@code Person}, to calculate tallest
     893      * person in each city:
     894      * <pre>{@code
     895      * Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
     896      * Map<City, Optional<Person>> tallestByCity
     897      *   = people.stream().collect(
     898      *     groupingBy(Person::getCity,
     899      *                reducing(BinaryOperator.maxBy(byHeight))));
     900      * }</pre>
     901      *
     902      * @param <T> element type for the input and output of the reduction
     903      * @param op a {@code BinaryOperator<T>} used to reduce the input elements
     904      * @return a {@code Collector} which implements the reduction operation
     905      *
     906      * @see #reducing(Object, BinaryOperator)
     907      * @see #reducing(Object, Function, BinaryOperator)
     908      */
     909     public static <T> Collector<T, ?, Optional<T>>
     910     reducing(BinaryOperator<T> op) {
     911         class OptionalBox implements Consumer<T> {
     912             T value = null;
     913             boolean present = false;
     914
     915             @Override
     916             public void accept(T t) {
     917                 if (present) {
     918                     value = op.apply(value, t);
     919                 }
     920                 else {
     921                     value = t;
     922                     present = true;
     923                 }
     924             }
     925         }
     926
     927         return new CollectorImpl<T, OptionalBox, Optional<T>>(
     928                 OptionalBox::new, OptionalBox::accept,
     929                 (a, b) -> { if (b.present) a.accept(b.value); return a; },
     930                 a -> Optional.ofNullable(a.value), CH_NOID);
     931     }
     932
     933     /**
     934      * Returns a {@code Collector} which performs a reduction of its
     935      * input elements under a specified mapping function and
     936      * {@code BinaryOperator}. This is a generalization of
     937      * {@link #reducing(Object, BinaryOperator)} which allows a transformation
     938      * of the elements before reduction.
     939      *
     940      * @apiNote
     941      * The {@code reducing()} collectors are most useful when used in a
     942      * multi-level reduction, downstream of {@code groupingBy} or
     943      * {@code partitioningBy}.  To perform a simple map-reduce on a stream,
     944      * use {@link Stream#map(Function)} and {@link Stream#reduce(Object, BinaryOperator)}
     945      * instead.
     946      *
     947      * <p>For example, given a stream of {@code Person}, to calculate the longest
     948      * last name of residents in each city:
     949      * <pre>{@code
     950      * Comparator<String> byLength = Comparator.comparing(String::length);
     951      * Map<City, String> longestLastNameByCity
     952      *   = people.stream().collect(
     953      *     groupingBy(Person::getCity,
     954      *                reducing("",
     955      *                         Person::getLastName,
     956      *                         BinaryOperator.maxBy(byLength))));
     957      * }</pre>
     958      *
     959      * @param <T> the type of the input elements
     960      * @param <U> the type of the mapped values
     961      * @param identity the identity value for the reduction (also, the value
     962      *                 that is returned when there are no input elements)
     963      * @param mapper a mapping function to apply to each input value
     964      * @param op a {@code BinaryOperator<U>} used to reduce the mapped values
     965      * @return a {@code Collector} implementing the map-reduce operation
     966      *
     967      * @see #reducing(Object, BinaryOperator)
     968      * @see #reducing(BinaryOperator)
     969      */
     970     public static <T, U>
     971     Collector<T, ?, U> reducing(U identity,
     972                                 Function<? super T, ? extends U> mapper,
     973                                 BinaryOperator<U> op) {
     974         return new CollectorImpl<>(
     975                 boxSupplier(identity),
     976                 (a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); },
     977                 (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
     978                 a -> a[0], CH_NOID);
     979     }
     980
     981     /**
     982      * Returns a {@code Collector} implementing a "group by" operation on
     983      * input elements of type {@code T}, grouping elements according to a
     984      * classification function, and returning the results in a {@code Map}.
     985      *
     986      * <p>The classification function maps elements to some key type {@code K}.
     987      * The collector produces a {@code Map<K, List<T>>} whose keys are the
     988      * values resulting from applying the classification function to the input
     989      * elements, and whose corresponding values are {@code List}s containing the
     990      * input elements which map to the associated key under the classification
     991      * function.
     992      *
     993      * <p>There are no guarantees on the type, mutability, serializability, or
     994      * thread-safety of the {@code Map} or {@code List} objects returned.
     995      * @implSpec
     996      * This produces a result similar to:
     997      * <pre>{@code
     998      *     groupingBy(classifier, toList());
     999      * }</pre>
    1000      *
    1001      * @implNote
    1002      * The returned {@code Collector} is not concurrent.  For parallel stream
    1003      * pipelines, the {@code combiner} function operates by merging the keys
    1004      * from one map into another, which can be an expensive operation.  If
    1005      * preservation of the order in which elements appear in the resulting {@code Map}
    1006      * collector is not required, using {@link #groupingByConcurrent(Function)}
    1007      * may offer better parallel performance.
    1008      *
    1009      * @param <T> the type of the input elements
    1010      * @param <K> the type of the keys
    1011      * @param classifier the classifier function mapping input elements to keys
    1012      * @return a {@code Collector} implementing the group-by operation
    1013      *
    1014      * @see #groupingBy(Function, Collector)
    1015      * @see #groupingBy(Function, Supplier, Collector)
    1016      * @see #groupingByConcurrent(Function)
    1017      */
    1018     public static <T, K> Collector<T, ?, Map<K, List<T>>>
    1019     groupingBy(Function<? super T, ? extends K> classifier) {
    1020         return groupingBy(classifier, toList());
    1021     }
    1022
    1023     /**
    1024      * Returns a {@code Collector} implementing a cascaded "group by" operation
    1025      * on input elements of type {@code T}, grouping elements according to a
    1026      * classification function, and then performing a reduction operation on
    1027      * the values associated with a given key using the specified downstream
    1028      * {@code Collector}.
    1029      *
    1030      * <p>The classification function maps elements to some key type {@code K}.
    1031      * The downstream collector operates on elements of type {@code T} and
    1032      * produces a result of type {@code D}. The resulting collector produces a
    1033      * {@code Map<K, D>}.
    1034      *
    1035      * <p>There are no guarantees on the type, mutability,
    1036      * serializability, or thread-safety of the {@code Map} returned.
    1037      *
    1038      * <p>For example, to compute the set of last names of people in each city:
    1039      * <pre>{@code
    1040      * Map<City, Set<String>> namesByCity
    1041      *   = people.stream().collect(
    1042      *     groupingBy(Person::getCity,
    1043      *                mapping(Person::getLastName,
    1044      *                        toSet())));
    1045      * }</pre>
    1046      *
    1047      * @implNote
    1048      * The returned {@code Collector} is not concurrent.  For parallel stream
    1049      * pipelines, the {@code combiner} function operates by merging the keys
    1050      * from one map into another, which can be an expensive operation.  If
    1051      * preservation of the order in which elements are presented to the downstream
    1052      * collector is not required, using {@link #groupingByConcurrent(Function, Collector)}
    1053      * may offer better parallel performance.
    1054      *
    1055      * @param <T> the type of the input elements
    1056      * @param <K> the type of the keys
    1057      * @param <A> the intermediate accumulation type of the downstream collector
    1058      * @param <D> the result type of the downstream reduction
    1059      * @param classifier a classifier function mapping input elements to keys
    1060      * @param downstream a {@code Collector} implementing the downstream reduction
    1061      * @return a {@code Collector} implementing the cascaded group-by operation
    1062      * @see #groupingBy(Function)
    1063      *
    1064      * @see #groupingBy(Function, Supplier, Collector)
    1065      * @see #groupingByConcurrent(Function, Collector)
    1066      */
    1067     public static <T, K, A, D>
    1068     Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
    1069                                           Collector<? super T, A, D> downstream) {
    1070         return groupingBy(classifier, HashMap::new, downstream);
    1071     }
    1072
    1073     /**
    1074      * Returns a {@code Collector} implementing a cascaded "group by" operation
    1075      * on input elements of type {@code T}, grouping elements according to a
    1076      * classification function, and then performing a reduction operation on
    1077      * the values associated with a given key using the specified downstream
    1078      * {@code Collector}.  The {@code Map} produced by the Collector is created
    1079      * with the supplied factory function.
    1080      *
    1081      * <p>The classification function maps elements to some key type {@code K}.
    1082      * The downstream collector operates on elements of type {@code T} and
    1083      * produces a result of type {@code D}. The resulting collector produces a
    1084      * {@code Map<K, D>}.
    1085      *
    1086      * <p>For example, to compute the set of last names of people in each city,
    1087      * where the city names are sorted:
    1088      * <pre>{@code
    1089      * Map<City, Set<String>> namesByCity
    1090      *   = people.stream().collect(
    1091      *     groupingBy(Person::getCity,
    1092      *                TreeMap::new,
    1093      *                mapping(Person::getLastName,
    1094      *                        toSet())));
    1095      * }</pre>
    1096      *
    1097      * @implNote
    1098      * The returned {@code Collector} is not concurrent.  For parallel stream
    1099      * pipelines, the {@code combiner} function operates by merging the keys
    1100      * from one map into another, which can be an expensive operation.  If
    1101      * preservation of the order in which elements are presented to the downstream
    1102      * collector is not required, using {@link #groupingByConcurrent(Function, Supplier, Collector)}
    1103      * may offer better parallel performance.
    1104      *
    1105      * @param <T> the type of the input elements
    1106      * @param <K> the type of the keys
    1107      * @param <A> the intermediate accumulation type of the downstream collector
    1108      * @param <D> the result type of the downstream reduction
    1109      * @param <M> the type of the resulting {@code Map}
    1110      * @param classifier a classifier function mapping input elements to keys
    1111      * @param downstream a {@code Collector} implementing the downstream reduction
    1112      * @param mapFactory a supplier providing a new empty {@code Map}
    1113      *                   into which the results will be inserted
    1114      * @return a {@code Collector} implementing the cascaded group-by operation
    1115      *
    1116      * @see #groupingBy(Function, Collector)
    1117      * @see #groupingBy(Function)
    1118      * @see #groupingByConcurrent(Function, Supplier, Collector)
    1119      */
    1120     public static <T, K, D, A, M extends Map<K, D>>
    1121     Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
    1122                                   Supplier<M> mapFactory,
    1123                                   Collector<? super T, A, D> downstream) {
    1124         Supplier<A> downstreamSupplier = downstream.supplier();
    1125         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
    1126         BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
    1127             K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
    1128             A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
    1129             downstreamAccumulator.accept(container, t);
    1130         };
    1131         BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner());
    1132         @SuppressWarnings("unchecked")
    1133         Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;
    1134
    1135         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
    1136             return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
    1137         }
    1138         else {
    1139             @SuppressWarnings("unchecked")
    1140             Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
    1141             Function<Map<K, A>, M> finisher = intermediate -> {
    1142                 intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
    1143                 @SuppressWarnings("unchecked")
    1144                 M castResult = (M) intermediate;
    1145                 return castResult;
    1146             };
    1147             return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
    1148         }
    1149     }
    1150
    1151     /**
    1152      * Returns a concurrent {@code Collector} implementing a "group by"
    1153      * operation on input elements of type {@code T}, grouping elements
    1154      * according to a classification function.
    1155      *
    1156      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
    1157      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
    1158      *
    1159      * <p>The classification function maps elements to some key type {@code K}.
    1160      * The collector produces a {@code ConcurrentMap<K, List<T>>} whose keys are the
    1161      * values resulting from applying the classification function to the input
    1162      * elements, and whose corresponding values are {@code List}s containing the
    1163      * input elements which map to the associated key under the classification
    1164      * function.
    1165      *
    1166      * <p>There are no guarantees on the type, mutability, or serializability
    1167      * of the {@code ConcurrentMap} or {@code List} objects returned, or of the
    1168      * thread-safety of the {@code List} objects returned.
    1169      * @implSpec
    1170      * This produces a result similar to:
    1171      * <pre>{@code
    1172      *     groupingByConcurrent(classifier, toList());
    1173      * }</pre>
    1174      *
    1175      * @param <T> the type of the input elements
    1176      * @param <K> the type of the keys
    1177      * @param classifier a classifier function mapping input elements to keys
    1178      * @return a concurrent, unordered {@code Collector} implementing the group-by operation
    1179      *
    1180      * @see #groupingBy(Function)
    1181      * @see #groupingByConcurrent(Function, Collector)
    1182      * @see #groupingByConcurrent(Function, Supplier, Collector)
    1183      */
    1184     public static <T, K>
    1185     Collector<T, ?, ConcurrentMap<K, List<T>>>
    1186     groupingByConcurrent(Function<? super T, ? extends K> classifier) {
    1187         return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
    1188     }
    1189
    1190     /**
    1191      * Returns a concurrent {@code Collector} implementing a cascaded "group by"
    1192      * operation on input elements of type {@code T}, grouping elements
    1193      * according to a classification function, and then performing a reduction
    1194      * operation on the values associated with a given key using the specified
    1195      * downstream {@code Collector}.
    1196      *
    1197      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
    1198      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
    1199      *
    1200      * <p>The classification function maps elements to some key type {@code K}.
    1201      * The downstream collector operates on elements of type {@code T} and
    1202      * produces a result of type {@code D}. The resulting collector produces a
    1203      * {@code ConcurrentMap<K, D>}.
    1204      *
    1205      * <p>There are no guarantees on the type, mutability, or serializability
    1206      * of the {@code ConcurrentMap} returned.
    1207      *
    1208      * <p>For example, to compute the set of last names of people in each city,
    1209      * where the city names are sorted:
    1210      * <pre>{@code
    1211      * ConcurrentMap<City, Set<String>> namesByCity
    1212      *   = people.stream().collect(
    1213      *     groupingByConcurrent(Person::getCity,
    1214      *                          mapping(Person::getLastName,
    1215      *                                  toSet())));
    1216      * }</pre>
    1217      *
    1218      * @param <T> the type of the input elements
    1219      * @param <K> the type of the keys
    1220      * @param <A> the intermediate accumulation type of the downstream collector
    1221      * @param <D> the result type of the downstream reduction
    1222      * @param classifier a classifier function mapping input elements to keys
    1223      * @param downstream a {@code Collector} implementing the downstream reduction
    1224      * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
    1225      *
    1226      * @see #groupingBy(Function, Collector)
    1227      * @see #groupingByConcurrent(Function)
    1228      * @see #groupingByConcurrent(Function, Supplier, Collector)
    1229      */
    1230     public static <T, K, A, D>
    1231     Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier,
    1232                                                               Collector<? super T, A, D> downstream) {
    1233         return groupingByConcurrent(classifier, ConcurrentHashMap::new, downstream);
    1234     }
    1235
    1236     /**
    1237      * Returns a concurrent {@code Collector} implementing a cascaded "group by"
    1238      * operation on input elements of type {@code T}, grouping elements
    1239      * according to a classification function, and then performing a reduction
    1240      * operation on the values associated with a given key using the specified
    1241      * downstream {@code Collector}.  The {@code ConcurrentMap} produced by the
    1242      * Collector is created with the supplied factory function.
    1243      *
    1244      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
    1245      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
    1246      *
    1247      * <p>The classification function maps elements to some key type {@code K}.
    1248      * The downstream collector operates on elements of type {@code T} and
    1249      * produces a result of type {@code D}. The resulting collector produces a
    1250      * {@code ConcurrentMap<K, D>}.
    1251      *
    1252      * <p>For example, to compute the set of last names of people in each city,
    1253      * where the city names are sorted:
    1254      * <pre>{@code
    1255      * ConcurrentMap<City, Set<String>> namesByCity
    1256      *   = people.stream().collect(
    1257      *     groupingByConcurrent(Person::getCity,
    1258      *                          ConcurrentSkipListMap::new,
    1259      *                          mapping(Person::getLastName,
    1260      *                                  toSet())));
    1261      * }</pre>
    1262      *
    1263      * @param <T> the type of the input elements
    1264      * @param <K> the type of the keys
    1265      * @param <A> the intermediate accumulation type of the downstream collector
    1266      * @param <D> the result type of the downstream reduction
    1267      * @param <M> the type of the resulting {@code ConcurrentMap}
    1268      * @param classifier a classifier function mapping input elements to keys
    1269      * @param downstream a {@code Collector} implementing the downstream reduction
    1270      * @param mapFactory a supplier providing a new empty {@code ConcurrentMap}
    1271      *                   into which the results will be inserted
    1272      * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
    1273      *
    1274      * @see #groupingByConcurrent(Function)
    1275      * @see #groupingByConcurrent(Function, Collector)
    1276      * @see #groupingBy(Function, Supplier, Collector)
    1277      */
    1278     public static <T, K, A, D, M extends ConcurrentMap<K, D>>
    1279     Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier,
    1280                                             Supplier<M> mapFactory,
    1281                                             Collector<? super T, A, D> downstream) {
    1282         Supplier<A> downstreamSupplier = downstream.supplier();
    1283         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
    1284         BinaryOperator<ConcurrentMap<K, A>> merger = Collectors.<K, A, ConcurrentMap<K, A>>mapMerger(downstream.combiner());
    1285         @SuppressWarnings("unchecked")
    1286         Supplier<ConcurrentMap<K, A>> mangledFactory = (Supplier<ConcurrentMap<K, A>>) mapFactory;
    1287         BiConsumer<ConcurrentMap<K, A>, T> accumulator;
    1288         if (downstream.characteristics().contains(Collector.Characteristics.CONCURRENT)) {
    1289             accumulator = (m, t) -> {
    1290                 K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
    1291                 A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
    1292                 downstreamAccumulator.accept(resultContainer, t);
    1293             };
    1294         }
    1295         else {
    1296             accumulator = (m, t) -> {
    1297                 K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
    1298                 A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
    1299                 synchronized (resultContainer) {
    1300                     downstreamAccumulator.accept(resultContainer, t);
    1301                 }
    1302             };
    1303         }
    1304
    1305         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
    1306             return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_CONCURRENT_ID);
    1307         }
    1308         else {
    1309             @SuppressWarnings("unchecked")
    1310             Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
    1311             Function<ConcurrentMap<K, A>, M> finisher = intermediate -> {
    1312                 intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
    1313                 @SuppressWarnings("unchecked")
    1314                 M castResult = (M) intermediate;
    1315                 return castResult;
    1316             };
    1317             return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID);
    1318         }
    1319     }
    1320
    1321     /**
    1322      * Returns a {@code Collector} which partitions the input elements according
    1323      * to a {@code Predicate}, and organizes them into a
    1324      * {@code Map<Boolean, List<T>>}.
    1325      *
    1326      * The returned {@code Map} always contains mappings for both
    1327      * {@code false} and {@code true} keys.
    1328      * There are no guarantees on the type, mutability,
    1329      * serializability, or thread-safety of the {@code Map} or {@code List}
    1330      * returned.
    1331      *
    1332      * @apiNote
    1333      * If a partition has no elements, its value in the result Map will be
    1334      * an empty List.
    1335      *
    1336      * @param <T> the type of the input elements
    1337      * @param predicate a predicate used for classifying input elements
    1338      * @return a {@code Collector} implementing the partitioning operation
    1339      *
    1340      * @see #partitioningBy(Predicate, Collector)
    1341      */
    1342     public static <T>
    1343     Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
    1344         return partitioningBy(predicate, toList());
    1345     }
    1346
    1347     /**
    1348      * Returns a {@code Collector} which partitions the input elements according
    1349      * to a {@code Predicate}, reduces the values in each partition according to
    1350      * another {@code Collector}, and organizes them into a
    1351      * {@code Map<Boolean, D>} whose values are the result of the downstream
    1352      * reduction.
    1353      *
    1354      * <p>
    1355      * The returned {@code Map} always contains mappings for both
    1356      * {@code false} and {@code true} keys.
    1357      * There are no guarantees on the type, mutability,
    1358      * serializability, or thread-safety of the {@code Map} returned.
    1359      *
    1360      * @apiNote
    1361      * If a partition has no elements, its value in the result Map will be
    1362      * obtained by calling the downstream collector's supplier function and then
    1363      * applying the finisher function.
    1364      *
    1365      * @param <T> the type of the input elements
    1366      * @param <A> the intermediate accumulation type of the downstream collector
    1367      * @param <D> the result type of the downstream reduction
    1368      * @param predicate a predicate used for classifying input elements
    1369      * @param downstream a {@code Collector} implementing the downstream
    1370      *                   reduction
    1371      * @return a {@code Collector} implementing the cascaded partitioning
    1372      *         operation
    1373      *
    1374      * @see #partitioningBy(Predicate)
    1375      */
    1376     public static <T, D, A>
    1377     Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
    1378                                                     Collector<? super T, A, D> downstream) {
    1379         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
    1380         BiConsumer<Partition<A>, T> accumulator = (result, t) ->
    1381                 downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t);
    1382         BinaryOperator<A> op = downstream.combiner();
    1383         BinaryOperator<Partition<A>> merger = (left, right) ->
    1384                 new Partition<>(op.apply(left.forTrue, right.forTrue),
    1385                                 op.apply(left.forFalse, right.forFalse));
    1386         Supplier<Partition<A>> supplier = () ->
    1387                 new Partition<>(downstream.supplier().get(),
    1388                                 downstream.supplier().get());
    1389         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
    1390             return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
    1391         }
    1392         else {
    1393             Function<Partition<A>, Map<Boolean, D>> finisher = par ->
    1394                     new Partition<>(downstream.finisher().apply(par.forTrue),
    1395                                     downstream.finisher().apply(par.forFalse));
    1396             return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
    1397         }
    1398     }
    1399
    1400     /**
    1401      * Returns a {@code Collector} that accumulates elements into a
    1402      * {@code Map} whose keys and values are the result of applying the provided
    1403      * mapping functions to the input elements.
    1404      *
    1405      * <p>If the mapped keys contain duplicates (according to
    1406      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
    1407      * thrown when the collection operation is performed.  If the mapped keys
    1408      * might have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
    1409      * instead.
    1410      *
    1411      * <p>There are no guarantees on the type, mutability, serializability,
    1412      * or thread-safety of the {@code Map} returned.
    1413      *
    1414      * @apiNote
    1415      * It is common for either the key or the value to be the input elements.
    1416      * In this case, the utility method
    1417      * {@link java.util.function.Function#identity()} may be helpful.
    1418      * For example, the following produces a {@code Map} mapping
    1419      * students to their grade point average:
    1420      * <pre>{@code
    1421      * Map<Student, Double> studentToGPA
    1422      *   = students.stream().collect(
    1423      *     toMap(Function.identity(),
    1424      *           student -> computeGPA(student)));
    1425      * }</pre>
    1426      * And the following produces a {@code Map} mapping a unique identifier to
    1427      * students:
    1428      * <pre>{@code
    1429      * Map<String, Student> studentIdToStudent
    1430      *   = students.stream().collect(
    1431      *     toMap(Student::getId,
    1432      *           Function.identity()));
    1433      * }</pre>
    1434      *
    1435      * @implNote
    1436      * The returned {@code Collector} is not concurrent.  For parallel stream
    1437      * pipelines, the {@code combiner} function operates by merging the keys
    1438      * from one map into another, which can be an expensive operation.  If it is
    1439      * not required that results are inserted into the {@code Map} in encounter
    1440      * order, using {@link #toConcurrentMap(Function, Function)}
    1441      * may offer better parallel performance.
    1442      *
    1443      * @param <T> the type of the input elements
    1444      * @param <K> the output type of the key mapping function
    1445      * @param <U> the output type of the value mapping function
    1446      * @param keyMapper a mapping function to produce keys
    1447      * @param valueMapper a mapping function to produce values
    1448      * @return a {@code Collector} which collects elements into a {@code Map}
    1449      * whose keys and values are the result of applying mapping functions to
    1450      * the input elements
    1451      *
    1452      * @see #toMap(Function, Function, BinaryOperator)
    1453      * @see #toMap(Function, Function, BinaryOperator, Supplier)
    1454      * @see #toConcurrentMap(Function, Function)
    1455      */
    1456     public static <T, K, U>
    1457     Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
    1458                                     Function<? super T, ? extends U> valueMapper) {
    1459         return new CollectorImpl<>(HashMap::new,
    1460                                    uniqKeysMapAccumulator(keyMapper, valueMapper),
    1461                                    uniqKeysMapMerger(),
    1462                                    CH_ID);
    1463     }
    1464
    1465     /**
    1466      * Returns a {@code Collector} that accumulates the input elements into an
    1467      * <a href="../Map.html#unmodifiable">unmodifiable Map</a>,
    1468      * whose keys and values are the result of applying the provided
    1469      * mapping functions to the input elements.
    1470      *
    1471      * <p>If the mapped keys contain duplicates (according to
    1472      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
    1473      * thrown when the collection operation is performed.  If the mapped keys
    1474      * might have duplicates, use {@link #toUnmodifiableMap(Function, Function, BinaryOperator)}
    1475      * to handle merging of the values.
    1476      *
    1477      * <p>The returned Collector disallows null keys and values. If either mapping function
    1478      * returns null, {@code NullPointerException} will be thrown.
    1479      *
    1480      * @param <T> the type of the input elements
    1481      * @param <K> the output type of the key mapping function
    1482      * @param <U> the output type of the value mapping function
    1483      * @param keyMapper a mapping function to produce keys, must be non-null
    1484      * @param valueMapper a mapping function to produce values, must be non-null
    1485      * @return a {@code Collector} which collects elements into an unmodifiable {@code Map}
    1486      * whose keys and values are the result of applying mapping functions to
    1487      * the input elements
    1488      * @throws NullPointerException if either keyMapper or valueMapper is null
    1489      *
    1490      * @see #toUnmodifiableMap(Function, Function, BinaryOperator)
    1491      * @since 10
    1492      */
    1493     @SuppressWarnings({"rawtypes", "unchecked"})
    1494     public static <T, K, U>
    1495     Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
    1496                                                 Function<? super T, ? extends U> valueMapper) {
    1497         Objects.requireNonNull(keyMapper, "keyMapper");
    1498         Objects.requireNonNull(valueMapper, "valueMapper");
    1499         return collectingAndThen(
    1500                 toMap(keyMapper, valueMapper),
    1501                 map -> (Map<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
    1502     }
    1503
    1504     /**
    1505      * Returns a {@code Collector} that accumulates elements into a
    1506      * {@code Map} whose keys and values are the result of applying the provided
    1507      * mapping functions to the input elements.
    1508      *
    1509      * <p>If the mapped
    1510      * keys contain duplicates (according to {@link Object#equals(Object)}),
    1511      * the value mapping function is applied to each equal element, and the
    1512      * results are merged using the provided merging function.
    1513      *
    1514      * <p>There are no guarantees on the type, mutability, serializability,
    1515      * or thread-safety of the {@code Map} returned.
    1516      *
    1517      * @apiNote
    1518      * There are multiple ways to deal with collisions between multiple elements
    1519      * mapping to the same key.  The other forms of {@code toMap} simply use
    1520      * a merge function that throws unconditionally, but you can easily write
    1521      * more flexible merge policies.  For example, if you have a stream
    1522      * of {@code Person}, and you want to produce a "phone book" mapping name to
    1523      * address, but it is possible that two persons have the same name, you can
    1524      * do as follows to gracefully deal with these collisions, and produce a
    1525      * {@code Map} mapping names to a concatenated list of addresses:
    1526      * <pre>{@code
    1527      * Map<String, String> phoneBook
    1528      *   = people.stream().collect(
    1529      *     toMap(Person::getName,
    1530      *           Person::getAddress,
    1531      *           (s, a) -> s + ", " + a));
    1532      * }</pre>
    1533      *
    1534      * @implNote
    1535      * The returned {@code Collector} is not concurrent.  For parallel stream
    1536      * pipelines, the {@code combiner} function operates by merging the keys
    1537      * from one map into another, which can be an expensive operation.  If it is
    1538      * not required that results are merged into the {@code Map} in encounter
    1539      * order, using {@link #toConcurrentMap(Function, Function, BinaryOperator)}
    1540      * may offer better parallel performance.
    1541      *
    1542      * @param <T> the type of the input elements
    1543      * @param <K> the output type of the key mapping function
    1544      * @param <U> the output type of the value mapping function
    1545      * @param keyMapper a mapping function to produce keys
    1546      * @param valueMapper a mapping function to produce values
    1547      * @param mergeFunction a merge function, used to resolve collisions between
    1548      *                      values associated with the same key, as supplied
    1549      *                      to {@link Map#merge(Object, Object, BiFunction)}
    1550      * @return a {@code Collector} which collects elements into a {@code Map}
    1551      * whose keys are the result of applying a key mapping function to the input
    1552      * elements, and whose values are the result of applying a value mapping
    1553      * function to all input elements equal to the key and combining them
    1554      * using the merge function
    1555      *
    1556      * @see #toMap(Function, Function)
    1557      * @see #toMap(Function, Function, BinaryOperator, Supplier)
    1558      * @see #toConcurrentMap(Function, Function, BinaryOperator)
    1559      */
    1560     public static <T, K, U>
    1561     Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
    1562                                     Function<? super T, ? extends U> valueMapper,
    1563                                     BinaryOperator<U> mergeFunction) {
    1564         return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
    1565     }
    1566
    1567
    1568     /**
    1569      * Returns a {@code Collector} that accumulates the input elements into an
    1570      * <a href="../Map.html#unmodifiable">unmodifiable Map</a>,
    1571      * whose keys and values are the result of applying the provided
    1572      * mapping functions to the input elements.
    1573      *
    1574      * <p>If the mapped
    1575      * keys contain duplicates (according to {@link Object#equals(Object)}),
    1576      * the value mapping function is applied to each equal element, and the
    1577      * results are merged using the provided merging function.
    1578      *
    1579      * <p>The returned Collector disallows null keys and values. If either mapping function
    1580      * returns null, {@code NullPointerException} will be thrown.
    1581      *
    1582      * @param <T> the type of the input elements
    1583      * @param <K> the output type of the key mapping function
    1584      * @param <U> the output type of the value mapping function
    1585      * @param keyMapper a mapping function to produce keys, must be non-null
    1586      * @param valueMapper a mapping function to produce values, must be non-null
    1587      * @param mergeFunction a merge function, used to resolve collisions between
    1588      *                      values associated with the same key, as supplied
    1589      *                      to {@link Map#merge(Object, Object, BiFunction)},
    1590      *                      must be non-null
    1591      * @return a {@code Collector} which collects elements into an unmodifiable {@code Map}
    1592      * whose keys are the result of applying a key mapping function to the input
    1593      * elements, and whose values are the result of applying a value mapping
    1594      * function to all input elements equal to the key and combining them
    1595      * using the merge function
    1596      * @throws NullPointerException if the keyMapper, valueMapper, or mergeFunction is null
    1597      *
    1598      * @see #toUnmodifiableMap(Function, Function)
    1599      * @since 10
    1600      */
    1601     @SuppressWarnings({"rawtypes", "unchecked"})
    1602     public static <T, K, U>
    1603     Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
    1604                                                 Function<? super T, ? extends U> valueMapper,
    1605                                                 BinaryOperator<U> mergeFunction) {
    1606         Objects.requireNonNull(keyMapper, "keyMapper");
    1607         Objects.requireNonNull(valueMapper, "valueMapper");
    1608         Objects.requireNonNull(mergeFunction, "mergeFunction");
    1609         return collectingAndThen(
    1610                 toMap(keyMapper, valueMapper, mergeFunction, HashMap::new),
    1611                 map -> (Map<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
    1612     }
    1613
    1614     /**
    1615      * Returns a {@code Collector} that accumulates elements into a
    1616      * {@code Map} whose keys and values are the result of applying the provided
    1617      * mapping functions to the input elements.
    1618      *
    1619      * <p>If the mapped
    1620      * keys contain duplicates (according to {@link Object#equals(Object)}),
    1621      * the value mapping function is applied to each equal element, and the
    1622      * results are merged using the provided merging function.  The {@code Map}
    1623      * is created by a provided supplier function.
    1624      *
    1625      * @implNote
    1626      * The returned {@code Collector} is not concurrent.  For parallel stream
    1627      * pipelines, the {@code combiner} function operates by merging the keys
    1628      * from one map into another, which can be an expensive operation.  If it is
    1629      * not required that results are merged into the {@code Map} in encounter
    1630      * order, using {@link #toConcurrentMap(Function, Function, BinaryOperator, Supplier)}
    1631      * may offer better parallel performance.
    1632      *
    1633      * @param <T> the type of the input elements
    1634      * @param <K> the output type of the key mapping function
    1635      * @param <U> the output type of the value mapping function
    1636      * @param <M> the type of the resulting {@code Map}
    1637      * @param keyMapper a mapping function to produce keys
    1638      * @param valueMapper a mapping function to produce values
    1639      * @param mergeFunction a merge function, used to resolve collisions between
    1640      *                      values associated with the same key, as supplied
    1641      *                      to {@link Map#merge(Object, Object, BiFunction)}
    1642      * @param mapFactory a supplier providing a new empty {@code Map}
    1643      *                   into which the results will be inserted
    1644      * @return a {@code Collector} which collects elements into a {@code Map}
    1645      * whose keys are the result of applying a key mapping function to the input
    1646      * elements, and whose values are the result of applying a value mapping
    1647      * function to all input elements equal to the key and combining them
    1648      * using the merge function
    1649      *
    1650      * @see #toMap(Function, Function)
    1651      * @see #toMap(Function, Function, BinaryOperator)
    1652      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
    1653      */
    1654     public static <T, K, U, M extends Map<K, U>>
    1655     Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
    1656                              Function<? super T, ? extends U> valueMapper,
    1657                              BinaryOperator<U> mergeFunction,
    1658                              Supplier<M> mapFactory) {
    1659         BiConsumer<M, T> accumulator
    1660                 = (map, element) -> map.merge(keyMapper.apply(element),
    1661                                               valueMapper.apply(element), mergeFunction);
    1662         return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_ID);
    1663     }
    1664
    1665     /**
    1666      * Returns a concurrent {@code Collector} that accumulates elements into a
    1667      * {@code ConcurrentMap} whose keys and values are the result of applying
    1668      * the provided mapping functions to the input elements.
    1669      *
    1670      * <p>If the mapped keys contain duplicates (according to
    1671      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
    1672      * thrown when the collection operation is performed.  If the mapped keys
    1673      * may have duplicates, use
    1674      * {@link #toConcurrentMap(Function, Function, BinaryOperator)} instead.
    1675      *
    1676      * <p>There are no guarantees on the type, mutability, or serializability
    1677      * of the {@code ConcurrentMap} returned.
    1678      *
    1679      * @apiNote
    1680      * It is common for either the key or the value to be the input elements.
    1681      * In this case, the utility method
    1682      * {@link java.util.function.Function#identity()} may be helpful.
    1683      * For example, the following produces a {@code ConcurrentMap} mapping
    1684      * students to their grade point average:
    1685      * <pre>{@code
    1686      * ConcurrentMap<Student, Double> studentToGPA
    1687      *   = students.stream().collect(
    1688      *     toConcurrentMap(Function.identity(),
    1689      *                     student -> computeGPA(student)));
    1690      * }</pre>
    1691      * And the following produces a {@code ConcurrentMap} mapping a
    1692      * unique identifier to students:
    1693      * <pre>{@code
    1694      * ConcurrentMap<String, Student> studentIdToStudent
    1695      *   = students.stream().collect(
    1696      *     toConcurrentMap(Student::getId,
    1697      *                     Function.identity()));
    1698      * }</pre>
    1699      *
    1700      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
    1701      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
    1702      *
    1703      * @param <T> the type of the input elements
    1704      * @param <K> the output type of the key mapping function
    1705      * @param <U> the output type of the value mapping function
    1706      * @param keyMapper the mapping function to produce keys
    1707      * @param valueMapper the mapping function to produce values
    1708      * @return a concurrent, unordered {@code Collector} which collects elements into a
    1709      * {@code ConcurrentMap} whose keys are the result of applying a key mapping
    1710      * function to the input elements, and whose values are the result of
    1711      * applying a value mapping function to the input elements
    1712      *
    1713      * @see #toMap(Function, Function)
    1714      * @see #toConcurrentMap(Function, Function, BinaryOperator)
    1715      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
    1716      */
    1717     public static <T, K, U>
    1718     Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
    1719                                                         Function<? super T, ? extends U> valueMapper) {
    1720         return new CollectorImpl<>(ConcurrentHashMap::new,
    1721                                    uniqKeysMapAccumulator(keyMapper, valueMapper),
    1722                                    uniqKeysMapMerger(),
    1723                                    CH_CONCURRENT_ID);
    1724     }
    1725
    1726     /**
    1727      * Returns a concurrent {@code Collector} that accumulates elements into a
    1728      * {@code ConcurrentMap} whose keys and values are the result of applying
    1729      * the provided mapping functions to the input elements.
    1730      *
    1731      * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}),
    1732      * the value mapping function is applied to each equal element, and the
    1733      * results are merged using the provided merging function.
    1734      *
    1735      * <p>There are no guarantees on the type, mutability, or serializability
    1736      * of the {@code ConcurrentMap} returned.
    1737      *
    1738      * @apiNote
    1739      * There are multiple ways to deal with collisions between multiple elements
    1740      * mapping to the same key.  The other forms of {@code toConcurrentMap} simply use
    1741      * a merge function that throws unconditionally, but you can easily write
    1742      * more flexible merge policies.  For example, if you have a stream
    1743      * of {@code Person}, and you want to produce a "phone book" mapping name to
    1744      * address, but it is possible that two persons have the same name, you can
    1745      * do as follows to gracefully deal with these collisions, and produce a
    1746      * {@code ConcurrentMap} mapping names to a concatenated list of addresses:
    1747      * <pre>{@code
    1748      * ConcurrentMap<String, String> phoneBook
    1749      *   = people.stream().collect(
    1750      *     toConcurrentMap(Person::getName,
    1751      *                     Person::getAddress,
    1752      *                     (s, a) -> s + ", " + a));
    1753      * }</pre>
    1754      *
    1755      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
    1756      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
    1757      *
    1758      * @param <T> the type of the input elements
    1759      * @param <K> the output type of the key mapping function
    1760      * @param <U> the output type of the value mapping function
    1761      * @param keyMapper a mapping function to produce keys
    1762      * @param valueMapper a mapping function to produce values
    1763      * @param mergeFunction a merge function, used to resolve collisions between
    1764      *                      values associated with the same key, as supplied
    1765      *                      to {@link Map#merge(Object, Object, BiFunction)}
    1766      * @return a concurrent, unordered {@code Collector} which collects elements into a
    1767      * {@code ConcurrentMap} whose keys are the result of applying a key mapping
    1768      * function to the input elements, and whose values are the result of
    1769      * applying a value mapping function to all input elements equal to the key
    1770      * and combining them using the merge function
    1771      *
    1772      * @see #toConcurrentMap(Function, Function)
    1773      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
    1774      * @see #toMap(Function, Function, BinaryOperator)
    1775      */
    1776     public static <T, K, U>
    1777     Collector<T, ?, ConcurrentMap<K,U>>
    1778     toConcurrentMap(Function<? super T, ? extends K> keyMapper,
    1779                     Function<? super T, ? extends U> valueMapper,
    1780                     BinaryOperator<U> mergeFunction) {
    1781         return toConcurrentMap(keyMapper, valueMapper, mergeFunction, ConcurrentHashMap::new);
    1782     }
    1783
    1784     /**
    1785      * Returns a concurrent {@code Collector} that accumulates elements into a
    1786      * {@code ConcurrentMap} whose keys and values are the result of applying
    1787      * the provided mapping functions to the input elements.
    1788      *
    1789      * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}),
    1790      * the value mapping function is applied to each equal element, and the
    1791      * results are merged using the provided merging function.  The
    1792      * {@code ConcurrentMap} is created by a provided supplier function.
    1793      *
    1794      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
    1795      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
    1796      *
    1797      * @param <T> the type of the input elements
    1798      * @param <K> the output type of the key mapping function
    1799      * @param <U> the output type of the value mapping function
    1800      * @param <M> the type of the resulting {@code ConcurrentMap}
    1801      * @param keyMapper a mapping function to produce keys
    1802      * @param valueMapper a mapping function to produce values
    1803      * @param mergeFunction a merge function, used to resolve collisions between
    1804      *                      values associated with the same key, as supplied
    1805      *                      to {@link Map#merge(Object, Object, BiFunction)}
    1806      * @param mapFactory a supplier providing a new empty {@code ConcurrentMap}
    1807      *                   into which the results will be inserted
    1808      * @return a concurrent, unordered {@code Collector} which collects elements into a
    1809      * {@code ConcurrentMap} whose keys are the result of applying a key mapping
    1810      * function to the input elements, and whose values are the result of
    1811      * applying a value mapping function to all input elements equal to the key
    1812      * and combining them using the merge function
    1813      *
    1814      * @see #toConcurrentMap(Function, Function)
    1815      * @see #toConcurrentMap(Function, Function, BinaryOperator)
    1816      * @see #toMap(Function, Function, BinaryOperator, Supplier)
    1817      */
    1818     public static <T, K, U, M extends ConcurrentMap<K, U>>
    1819     Collector<T, ?, M> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
    1820                                        Function<? super T, ? extends U> valueMapper,
    1821                                        BinaryOperator<U> mergeFunction,
    1822                                        Supplier<M> mapFactory) {
    1823         BiConsumer<M, T> accumulator
    1824                 = (map, element) -> map.merge(keyMapper.apply(element),
    1825                                               valueMapper.apply(element), mergeFunction);
    1826         return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_CONCURRENT_ID);
    1827     }
    1828
    1829     /**
    1830      * Returns a {@code Collector} which applies an {@code int}-producing
    1831      * mapping function to each input element, and returns summary statistics
    1832      * for the resulting values.
    1833      *
    1834      * @param <T> the type of the input elements
    1835      * @param mapper a mapping function to apply to each element
    1836      * @return a {@code Collector} implementing the summary-statistics reduction
    1837      *
    1838      * @see #summarizingDouble(ToDoubleFunction)
    1839      * @see #summarizingLong(ToLongFunction)
    1840      */
    1841     public static <T>
    1842     Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) {
    1843         return new CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>(
    1844                 IntSummaryStatistics::new,
    1845                 (r, t) -> r.accept(mapper.applyAsInt(t)),
    1846                 (l, r) -> { l.combine(r); return l; }, CH_ID);
    1847     }
    1848
    1849     /**
    1850      * Returns a {@code Collector} which applies an {@code long}-producing
    1851      * mapping function to each input element, and returns summary statistics
    1852      * for the resulting values.
    1853      *
    1854      * @param <T> the type of the input elements
    1855      * @param mapper the mapping function to apply to each element
    1856      * @return a {@code Collector} implementing the summary-statistics reduction
    1857      *
    1858      * @see #summarizingDouble(ToDoubleFunction)
    1859      * @see #summarizingInt(ToIntFunction)
    1860      */
    1861     public static <T>
    1862     Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) {
    1863         return new CollectorImpl<T, LongSummaryStatistics, LongSummaryStatistics>(
    1864                 LongSummaryStatistics::new,
    1865                 (r, t) -> r.accept(mapper.applyAsLong(t)),
    1866                 (l, r) -> { l.combine(r); return l; }, CH_ID);
    1867     }
    1868
    1869     /**
    1870      * Returns a {@code Collector} which applies an {@code double}-producing
    1871      * mapping function to each input element, and returns summary statistics
    1872      * for the resulting values.
    1873      *
    1874      * @param <T> the type of the input elements
    1875      * @param mapper a mapping function to apply to each element
    1876      * @return a {@code Collector} implementing the summary-statistics reduction
    1877      *
    1878      * @see #summarizingLong(ToLongFunction)
    1879      * @see #summarizingInt(ToIntFunction)
    1880      */
    1881     public static <T>
    1882     Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) {
    1883         return new CollectorImpl<T, DoubleSummaryStatistics, DoubleSummaryStatistics>(
    1884                 DoubleSummaryStatistics::new,
    1885                 (r, t) -> r.accept(mapper.applyAsDouble(t)),
    1886                 (l, r) -> { l.combine(r); return l; }, CH_ID);
    1887     }
    1888
    1889     /**
    1890      * Implementation class used by partitioningBy.
    1891      */
    1892     private static final class Partition<T>
    1893             extends AbstractMap<Boolean, T>
    1894             implements Map<Boolean, T> {
    1895         final T forTrue;
    1896         final T forFalse;
    1897
    1898         Partition(T forTrue, T forFalse) {
    1899             this.forTrue = forTrue;
    1900             this.forFalse = forFalse;
    1901         }
    1902
    1903         @Override
    1904         public Set<Map.Entry<Boolean, T>> entrySet() {
    1905             return new AbstractSet<>() {
    1906                 @Override
    1907                 public Iterator<Map.Entry<Boolean, T>> iterator() {
    1908                     Map.Entry<Boolean, T> falseEntry = new SimpleImmutableEntry<>(false, forFalse);
    1909                     Map.Entry<Boolean, T> trueEntry = new SimpleImmutableEntry<>(true, forTrue);
    1910                     return List.of(falseEntry, trueEntry).iterator();
    1911                 }
    1912
    1913                 @Override
    1914                 public int size() {
    1915                     return 2;
    1916                 }
    1917             };
    1918         }
    1919     }
    1920 }