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