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