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