1 /*
   2  * Copyright (c) 2012, 2013, 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.Arrays;
  31 import java.util.Collection;
  32 import java.util.Collections;
  33 import java.util.Comparator;
  34 import java.util.DoubleSummaryStatistics;
  35 import java.util.EnumSet;
  36 import java.util.HashMap;
  37 import java.util.HashSet;
  38 import java.util.IntSummaryStatistics;
  39 import java.util.Iterator;
  40 import java.util.List;
  41 import java.util.LongSummaryStatistics;
  42 import java.util.Map;
  43 import java.util.Objects;
  44 import java.util.Optional;
  45 import java.util.Set;
  46 import java.util.StringJoiner;
  47 import java.util.concurrent.ConcurrentHashMap;
  48 import java.util.concurrent.ConcurrentMap;
  49 import java.util.function.BiConsumer;
  50 import java.util.function.BiFunction;
  51 import java.util.function.BinaryOperator;
  52 import java.util.function.Consumer;
  53 import java.util.function.Function;
  54 import java.util.function.Predicate;
  55 import java.util.function.Supplier;
  56 import java.util.function.ToDoubleFunction;
  57 import java.util.function.ToIntFunction;
  58 import java.util.function.ToLongFunction;
  59 
  60 /**
  61  * Implementations of {@link Collector} that implement various useful reduction
  62  * operations, such as accumulating elements into collections, summarizing
  63  * elements according to various criteria, etc.
  64  *
  65  * <p>The following are examples of using the predefined {@code Collector}
  66  * implementations in {@link Collectors} with the {@code Stream} API to perform
  67  * mutable reduction tasks:
  68  *
  69  * <pre>{@code
  70  *     // Accumulate names into a List
  71  *     List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());
  72  *
  73  *     // Accumulate names into a TreeSet
  74  *     Set<String> list = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));
  75  *
  76  *     // Convert elements to strings and concatenate them, separated by commas
  77  *     String joined = things.stream()
  78  *                           .map(Object::toString)
  79  *                           .collect(Collectors.joining(", "));
  80  *
  81  *     // Find highest-paid employee
  82  *     Employee highestPaid = employees.stream()
  83  *                                     .collect(Collectors.maxBy(Comparator.comparing(Employee::getSalary)))
  84  *                                     .get();
  85  *
  86  *     // Group employees by department
  87  *     Map<Department, List<Employee>> byDept
  88  *         = employees.stream()
  89  *                    .collect(Collectors.groupingBy(Employee::getDepartment));
  90  *
  91  *     // Find highest-paid employee by department
  92  *     Map<Department, Optional<Employee>> highestPaidByDept
  93  *         = employees.stream()
  94  *                    .collect(Collectors.groupingBy(Employee::getDepartment,
  95  *                                                   Collectors.maxBy(Comparator.comparing(Employee::getSalary))));
  96  *
  97  *     // Partition students into passing and failing
  98  *     Map<Boolean, List<Student>> passingFailing =
  99  *         students.stream()
 100  *                 .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
 101  *
 102  * }</pre>
 103  *
 104  * TODO explanation of parallel collection
 105  *
 106  * @since 1.8
 107  */
 108 public final class Collectors {
 109 
 110     static final Set<Collector.Characteristics> CH_CONCURRENT_ID
 111             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
 112                                                      Collector.Characteristics.UNORDERED,
 113                                                      Collector.Characteristics.IDENTITY_FINISH));
 114     static final Set<Collector.Characteristics> CH_CONCURRENT_NOID
 115             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
 116                                                      Collector.Characteristics.UNORDERED));
 117     static final Set<Collector.Characteristics> CH_ID
 118             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
 119     static final Set<Collector.Characteristics> CH_UNORDERED_ID
 120             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
 121                                                      Collector.Characteristics.IDENTITY_FINISH));
 122     static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
 123 
 124     private Collectors() { }
 125 
 126     /**
 127      * Returns a merge function, suitable for use in
 128      * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or
 129      * {@link #toMap(Function, Function, BinaryOperator) toMap()}, which always
 130      * throws {@code IllegalStateException}.  This can be used to enforce the
 131      * assumption that the elements being collected are distinct.
 132      *
 133      * @param <T> the type of input arguments to the merge function
 134      * @return a merge function which always throw {@code IllegalStateException}
 135      */
 136     private static <T> BinaryOperator<T> throwingMerger() {
 137         return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
 138     }
 139 
 140     /**
 141      * Simple implementation class for {@code Collector}.
 142      *
 143      * @param <T> the type of elements to be collected
 144      * @param <R> the type of the result
 145      */
 146     static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
 147         private final Supplier<A> supplier;
 148         private final BiConsumer<A, T> accumulator;
 149         private final BinaryOperator<A> combiner;
 150         private final Function<A, R> finisher;
 151         private final Set<Characteristics> characteristics;
 152 
 153         CollectorImpl(Supplier<A> supplier,
 154                       BiConsumer<A, T> accumulator,
 155                       BinaryOperator<A> combiner,
 156                       Function<A,R> finisher,
 157                       Set<Characteristics> characteristics) {
 158             this.supplier = supplier;
 159             this.accumulator = accumulator;
 160             this.combiner = combiner;
 161             this.finisher = finisher;
 162             this.characteristics = characteristics;
 163         }
 164 
 165         CollectorImpl(Supplier<A> supplier,
 166                       BiConsumer<A, T> accumulator,
 167                       BinaryOperator<A> combiner,
 168                       Set<Characteristics> characteristics) {
 169             this(supplier, accumulator, combiner, i -> (R) i, characteristics);
 170         }
 171 
 172         @Override
 173         public BiConsumer<A, T> accumulator() {
 174             return accumulator;
 175         }
 176 
 177         @Override
 178         public Supplier<A> supplier() {
 179             return supplier;
 180         }
 181 
 182         @Override
 183         public BinaryOperator<A> combiner() {
 184             return combiner;
 185         }
 186 
 187         @Override
 188         public Function<A, R> finisher() {
 189             return finisher;
 190         }
 191 
 192         @Override
 193         public Set<Characteristics> characteristics() {
 194             return characteristics;
 195         }
 196     }
 197 
 198     /**
 199      * Returns a {@code Collector} that accumulates the input elements into a
 200      * new {@code Collection}, in encounter order.  The {@code Collection} is
 201      * created by the provided factory.
 202      *
 203      * @param <T> the type of the input elements
 204      * @param <C> the type of the resulting {@code Collection}
 205      * @param collectionFactory a {@code Supplier} which returns a new, empty
 206      * {@code Collection} of the appropriate type
 207      * @return a {@code Collector} which collects all the input elements into a
 208      * {@code Collection}, in encounter order
 209      */
 210     public static <T, C extends Collection<T>>
 211     Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
 212         return new CollectorImpl<>(collectionFactory, Collection::add,
 213                                    (r1, r2) -> { r1.addAll(r2); return r1; },
 214                                    CH_ID);
 215     }
 216 
 217     /**
 218      * Returns a {@code Collector} that accumulates the input elements into a
 219      * new {@code List}. There are no guarantees on the type, mutability,
 220      * serializability, or thread-safety of the {@code List} returned.
 221      *
 222      * @param <T> the type of the input elements
 223      * @return a {@code Collector} which collects all the input elements into a
 224      * {@code List}, in encounter order
 225      */
 226     public static <T>
 227     Collector<T, ?, List<T>> toList() {
 228         return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
 229                                    (left, right) -> { left.addAll(right); return left; },
 230                                    CH_ID);
 231     }
 232 
 233     /**
 234      * Returns a {@code Collector} that accumulates the input elements into a
 235      * new {@code Set}. There are no guarantees on the type, mutability,
 236      * serializability, or thread-safety of the {@code Set} returned.
 237      *
 238      * <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
 239      * Collector.
 240      *
 241      * @param <T> the type of the input elements
 242      * @return a {@code Collector} which collects all the input elements into a
 243      * {@code Set}
 244      */
 245     public static <T>
 246     Collector<T, ?, Set<T>> toSet() {
 247         return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
 248                                    (left, right) -> { left.addAll(right); return left; },
 249                                    CH_UNORDERED_ID);
 250     }
 251 
 252     /**
 253      * Returns a {@code Collector} that concatenates the input elements into a
 254      * {@code String}, in encounter order.
 255      *
 256      * @return a {@code Collector} that concatenates the input elements into a
 257      * {@code String}, in encounter order
 258      */
 259     public static Collector<CharSequence, ?, String> joining() {
 260         return new CollectorImpl<CharSequence, StringBuilder, String>(
 261                 StringBuilder::new, StringBuilder::append,
 262                 (r1, r2) -> { r1.append(r2); return r1; },
 263                 StringBuilder::toString, CH_NOID);
 264     }
 265 
 266     /**
 267      * Returns a {@code Collector} that concatenates the input elements,
 268      * separated by the specified delimiter, in encounter order.
 269      *
 270      * @param delimiter the delimiter to be used between each element
 271      * @return A {@code Collector} which concatenates CharSequence elements,
 272      * separated by the specified delimiter, in encounter order
 273      */
 274     public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {
 275         return joining(delimiter, "", "");
 276     }
 277 
 278     /**
 279      * Returns a {@code Collector} that concatenates the input elements,
 280      * separated by the specified delimiter, with the specified prefix and
 281      * suffix, in encounter order.
 282      *
 283      * @param delimiter the delimiter to be used between each element
 284      * @param  prefix the sequence of characters to be used at the beginning
 285      *                of the joined result
 286      * @param  suffix the sequence of characters to be used at the end
 287      *                of the joined result
 288      * @return A {@code Collector} which concatenates CharSequence elements,
 289      * separated by the specified delimiter, in encounter order
 290      */
 291     public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
 292                                                              CharSequence prefix,
 293                                                              CharSequence suffix) {
 294         return new CollectorImpl<>(
 295                 () -> new StringJoiner(delimiter, prefix, suffix),
 296                 StringJoiner::add, StringJoiner::merge,
 297                 StringJoiner::toString, CH_NOID);
 298     }
 299 
 300     /**
 301      * {@code BinaryOperator<Map>} that merges the contents of its right
 302      * argument into its left argument, using the provided merge function to
 303      * handle duplicate keys.
 304      *
 305      * @param <K> type of the map keys
 306      * @param <V> type of the map values
 307      * @param <M> type of the map
 308      * @param mergeFunction A merge function suitable for
 309      * {@link Map#merge(Object, Object, BiFunction) Map.merge()}
 310      * @return a merge function for two maps
 311      */
 312     private static <K, V, M extends Map<K,V>>
 313     BinaryOperator<M> mapMerger(BinaryOperator<V> mergeFunction) {
 314         return (m1, m2) -> {
 315             for (Map.Entry<K,V> e : m2.entrySet())
 316                 m1.merge(e.getKey(), e.getValue(), mergeFunction);
 317             return m1;
 318         };
 319     }
 320 
 321     /**
 322      * Adapts a {@code Collector} accepting elements of type {@code U} to one
 323      * accepting elements of type {@code T} by applying a mapping function to
 324      * each input element before accumulation.
 325      *
 326      * @apiNote
 327      * The {@code mapping()} collectors are most useful when used in a
 328      * multi-level reduction, such as downstream of a {@code groupingBy} or
 329      * {@code partitioningBy}.  For example, given a stream of
 330      * {@code Person}, to accumulate the set of last names in each city:
 331      * <pre>{@code
 332      *     Map<City, Set<String>> lastNamesByCity
 333      *         = people.stream().collect(groupingBy(Person::getCity,
 334      *                                              mapping(Person::getLastName, toSet())));
 335      * }</pre>
 336      *
 337      * @param <T> the type of the input elements
 338      * @param <U> type of elements accepted by downstream collector
 339      * @param <A> intermediate accumulation type of the downstream collector
 340      * @param <R> result type of collector
 341      * @param mapper a function to be applied to the input elements
 342      * @param downstream a collector which will accept mapped values
 343      * @return a collector which applies the mapping function to the input
 344      * elements and provides the mapped results to the downstream collector
 345      */
 346     public static <T, U, A, R>
 347     Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
 348                                Collector<? super U, A, R> downstream) {
 349         BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
 350         return new CollectorImpl<>(downstream.supplier(),
 351                                    (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
 352                                    downstream.combiner(), downstream.finisher(),
 353                                    downstream.characteristics());
 354     }
 355 
 356     /**
 357      * Returns a {@code Collector} accepting elements of type {@code T} that
 358      * counts the number of input elements.  If no elements are present, the
 359      * result is 0.
 360      *
 361      * @implSpec
 362      * This produces a result equivalent to:
 363      * <pre>{@code
 364      *     reducing(0L, e -> 1L, Long::sum)
 365      * }</pre>
 366      *
 367      * @param <T> the type of the input elements
 368      * @return a {@code Collector} that counts the input elements
 369      */
 370     public static <T> Collector<T, ?, Long>
 371     counting() {
 372         return reducing(0L, e -> 1L, Long::sum);
 373     }
 374 
 375     /**
 376      * Returns a {@code Collector} that produces the minimal element according
 377      * to a given {@code Comparator}, described as an {@code Optional<T>}.
 378      *
 379      * @implSpec
 380      * This produces a result equivalent to:
 381      * <pre>{@code
 382      *     reducing(BinaryOperator.minBy(comparator))
 383      * }</pre>
 384      *
 385      * @param <T> the type of the input elements
 386      * @param comparator a {@code Comparator} for comparing elements
 387      * @return a {@code Collector} that produces the minimal value
 388      */
 389     public static <T> Collector<T, ?, Optional<T>>
 390     minBy(Comparator<? super T> comparator) {
 391         return reducing(BinaryOperator.minBy(comparator));
 392     }
 393 
 394     /**
 395      * Returns a {@code Collector} that produces the maximal element according
 396      * to a given {@code Comparator}, described as an {@code Optional<T>}.
 397      *
 398      * @implSpec
 399      * This produces a result equivalent to:
 400      * <pre>{@code
 401      *     reducing(BinaryOperator.maxBy(comparator))
 402      * }</pre>
 403      *
 404      * @param <T> the type of the input elements
 405      * @param comparator a {@code Comparator} for comparing elements
 406      * @return a {@code Collector} that produces the maximal value
 407      */
 408     public static <T> Collector<T, ?, Optional<T>>
 409     maxBy(Comparator<? super T> comparator) {
 410         return reducing(BinaryOperator.maxBy(comparator));
 411     }
 412 
 413     /**
 414      * Returns a {@code Collector} that produces the sum of a integer-valued
 415      * function applied to the input elements.  If no elements are present,
 416      * the result is 0.
 417      *
 418      * @param <T> the type of the input elements
 419      * @param mapper a function extracting the property to be summed
 420      * @return a {@code Collector} that produces the sum of a derived property
 421      */
 422     public static <T> Collector<T, ?, Integer>
 423     summingInt(ToIntFunction<? super T> mapper) {
 424         return new CollectorImpl<T, int[], Integer>(
 425                 () -> new int[1],
 426                 (a, t) -> { a[0] += mapper.applyAsInt(t); },
 427                 (a, b) -> { a[0] += b[0]; return a; },
 428                 a -> a[0], CH_NOID);
 429     }
 430 
 431     /**
 432      * Returns a {@code Collector} that produces the sum of a long-valued
 433      * function applied to the input elements.  If no elements are present,
 434      * the result is 0.
 435      *
 436      * @param <T> the type of the input elements
 437      * @param mapper a function extracting the property to be summed
 438      * @return a {@code Collector} that produces the sum of a derived property
 439      */
 440     public static <T> Collector<T, ?, Long>
 441     summingLong(ToLongFunction<? super T> mapper) {
 442         return new CollectorImpl<T, long[], Long>(
 443                 () -> new long[1],
 444                 (a, t) -> { a[0] += mapper.applyAsLong(t); },
 445                 (a, b) -> { a[0] += b[0]; return a; },
 446                 a -> a[0], CH_NOID);
 447     }
 448 
 449     /**
 450      * Returns a {@code Collector} that produces the sum of a double-valued
 451      * function applied to the input elements.  If no elements are present,
 452      * the result is 0.
 453      *
 454      * <p>The sum returned can vary depending upon the order in which
 455      * values are recorded, due to accumulated rounding error in
 456      * addition of values of differing magnitudes. Values sorted by increasing
 457      * absolute magnitude tend to yield more accurate results.  If any recorded
 458      * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
 459      * sum will be {@code NaN}.
 460      *
 461      * @param <T> the type of the input elements
 462      * @param mapper a function extracting the property to be summed
 463      * @return a {@code Collector} that produces the sum of a derived property
 464      */
 465     public static <T> Collector<T, ?, Double>
 466     summingDouble(ToDoubleFunction<? super T> mapper) {
 467         return new CollectorImpl<T, double[], Double>(
 468                 () -> new double[1],
 469                 (a, t) -> { a[0] += mapper.applyAsDouble(t); },
 470                 (a, b) -> { a[0] += b[0]; return a; },
 471                 a -> a[0], CH_NOID);
 472     }
 473 
 474     /**
 475      * Returns a {@code Collector} that produces the average of an integer-valued
 476      * function applied to the input elements.  If no elements are present,
 477      * the result is 0.
 478      *
 479      * @param <T> the type of the input elements
 480      * @param mapper a function extracting the property to be summed
 481      * @return a {@code Collector} that produces the sum of a derived property
 482      */
 483     public static <T> Collector<T, ?, Double>
 484     averagingInt(ToIntFunction<? super T> mapper) {
 485         return new CollectorImpl<T, long[], Double>(
 486                 () -> new long[2],
 487                 (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; },
 488                 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
 489                 a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);
 490     }
 491 
 492     /**
 493      * Returns a {@code Collector} that produces the average of a long-valued
 494      * function applied to the input elements.  If no elements are present,
 495      * the result is 0.
 496      *
 497      * @param <T> the type of the input elements
 498      * @param mapper a function extracting the property to be summed
 499      * @return a {@code Collector} that produces the sum of a derived property
 500      */
 501     public static <T> Collector<T, ?, Double>
 502     averagingLong(ToLongFunction<? super T> mapper) {
 503         return new CollectorImpl<T, long[], Double>(
 504                 () -> new long[2],
 505                 (a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; },
 506                 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
 507                 a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);
 508     }
 509 
 510     /**
 511      * Returns a {@code Collector} that produces the average of a double-valued
 512      * function applied to the input elements.  If no elements are present,
 513      * the result is 0.
 514      *
 515      * <p>The average returned can vary depending upon the order in which
 516      * values are recorded, due to accumulated rounding error in
 517      * addition of values of differing magnitudes. Values sorted by increasing
 518      * absolute magnitude tend to yield more accurate results.  If any recorded
 519      * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
 520      * average will be {@code NaN}.
 521      *
 522      * @param <T> the type of the input elements
 523      * @param mapper a function extracting the property to be summed
 524      * @return a {@code Collector} that produces the sum of a derived property
 525      */
 526     public static <T> Collector<T, ?, Double>
 527     averagingDouble(ToDoubleFunction<? super T> mapper) {
 528         return new CollectorImpl<T, double[], Double>(
 529                 () -> new double[2],
 530                 (a, t) -> { a[0] += mapper.applyAsDouble(t); a[1]++; },
 531                 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
 532                 a -> (a[1] == 0) ? 0.0d : a[0] / a[1], CH_NOID);
 533     }
 534 
 535     /**
 536      * Returns a {@code Collector} which performs a reduction of its
 537      * input elements under a specified {@code BinaryOperator} using the
 538      * provided identity.
 539      *
 540      * @apiNote
 541      * The {@code reducing()} collectors are most useful when used in a
 542      * multi-level reduction, downstream of {@code groupingBy} or
 543      * {@code partitioningBy}.  To perform a simple reduction on a stream,
 544      * use {@link Stream#reduce(Object, BinaryOperator)}} instead.
 545      *
 546      * @param <T> element type for the input and output of the reduction
 547      * @param identity the identity value for the reduction (also, the value
 548      *                 that is returned when there are no input elements)
 549      * @param op a {@code BinaryOperator<T>} used to reduce the input elements
 550      * @return a {@code Collector} which implements the reduction operation
 551      *
 552      * @see #reducing(BinaryOperator)
 553      * @see #reducing(Object, Function, BinaryOperator)
 554      */
 555     public static <T> Collector<T, ?, T>
 556     reducing(T identity, BinaryOperator<T> op) {
 557         return new CollectorImpl<>(
 558                 boxSupplier(identity),
 559                 (a, t) -> { a[0] = op.apply(a[0], t); },
 560                 (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
 561                 a -> a[0],
 562                 CH_NOID);
 563     }
 564 
 565     @SuppressWarnings("unchecked")
 566     private static <T> Supplier<T[]> boxSupplier(T identity) {
 567         return () -> (T[]) new Object[] { identity };
 568     }
 569 
 570     /**
 571      * Returns a {@code Collector} which performs a reduction of its
 572      * input elements under a specified {@code BinaryOperator}.  The result
 573      * is described as an {@code Optional<T>}.
 574      *
 575      * @apiNote
 576      * The {@code reducing()} collectors are most useful when used in a
 577      * multi-level reduction, downstream of {@code groupingBy} or
 578      * {@code partitioningBy}.  To perform a simple reduction on a stream,
 579      * use {@link Stream#reduce(BinaryOperator)} instead.
 580      *
 581      * <p>For example, given a stream of {@code Person}, to calculate tallest
 582      * person in each city:
 583      * <pre>{@code
 584      *     Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
 585      *     Map<City, Person> tallestByCity
 586      *         = people.stream().collect(groupingBy(Person::getCity, reducing(BinaryOperator.maxBy(byHeight))));
 587      * }</pre>
 588      *
 589      * @param <T> element type for the input and output of the reduction
 590      * @param op a {@code BinaryOperator<T>} used to reduce the input elements
 591      * @return a {@code Collector} which implements the reduction operation
 592      *
 593      * @see #reducing(Object, BinaryOperator)
 594      * @see #reducing(Object, Function, BinaryOperator)
 595      */
 596     public static <T> Collector<T, ?, Optional<T>>
 597     reducing(BinaryOperator<T> op) {
 598         class OptionalBox implements Consumer<T> {
 599             T value = null;
 600             boolean present = false;
 601 
 602             @Override
 603             public void accept(T t) {
 604                 if (present) {
 605                     value = op.apply(value, t);
 606                 }
 607                 else {
 608                     value = t;
 609                     present = true;
 610                 }
 611             }
 612         }
 613 
 614         return new CollectorImpl<T, OptionalBox, Optional<T>>(
 615                 OptionalBox::new, OptionalBox::accept,
 616                 (a, b) -> { if (b.present) a.accept(b.value); return a; },
 617                 a -> Optional.ofNullable(a.value), CH_NOID);
 618     }
 619 
 620     /**
 621      * Returns a {@code Collector} which performs a reduction of its
 622      * input elements under a specified mapping function and
 623      * {@code BinaryOperator}. This is a generalization of
 624      * {@link #reducing(Object, BinaryOperator)} which allows a transformation
 625      * of the elements before reduction.
 626      *
 627      * @apiNote
 628      * The {@code reducing()} collectors are most useful when used in a
 629      * multi-level reduction, downstream of {@code groupingBy} or
 630      * {@code partitioningBy}.  To perform a simple map-reduce on a stream,
 631      * use {@link Stream#map(Function)} and {@link Stream#reduce(Object, BinaryOperator)}
 632      * instead.
 633      *
 634      * <p>For example, given a stream of {@code Person}, to calculate the longest
 635      * last name of residents in each city:
 636      * <pre>{@code
 637      *     Comparator<String> byLength = Comparator.comparing(String::length);
 638      *     Map<City, String> longestLastNameByCity
 639      *         = people.stream().collect(groupingBy(Person::getCity,
 640      *                                              reducing(Person::getLastName, BinaryOperator.maxBy(byLength))));
 641      * }</pre>
 642      *
 643      * @param <T> the type of the input elements
 644      * @param <U> the type of the mapped values
 645      * @param identity the identity value for the reduction (also, the value
 646      *                 that is returned when there are no input elements)
 647      * @param mapper a mapping function to apply to each input value
 648      * @param op a {@code BinaryOperator<U>} used to reduce the mapped values
 649      * @return a {@code Collector} implementing the map-reduce operation
 650      *
 651      * @see #reducing(Object, BinaryOperator)
 652      * @see #reducing(BinaryOperator)
 653      */
 654     public static <T, U>
 655     Collector<T, ?, U> reducing(U identity,
 656                                 Function<? super T, ? extends U> mapper,
 657                                 BinaryOperator<U> op) {
 658         return new CollectorImpl<>(
 659                 boxSupplier(identity),
 660                 (a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); },
 661                 (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
 662                 a -> a[0], CH_NOID);
 663     }
 664 
 665     /**
 666      * Returns a {@code Collector} implementing a "group by" operation on
 667      * input elements of type {@code T}, grouping elements according to a
 668      * classification function, and returning the results in a {@code Map}.
 669      *
 670      * <p>The classification function maps elements to some key type {@code K}.
 671      * The collector produces a {@code Map<K, List<T>>} whose keys are the
 672      * values resulting from applying the classification function to the input
 673      * elements, and whose corresponding values are {@code List}s containing the
 674      * input elements which map to the associated key under the classification
 675      * function.
 676      *
 677      * <p>There are no guarantees on the type, mutability, serializability, or
 678      * thread-safety of the {@code Map} or {@code List} objects returned.
 679      * @implSpec
 680      * This produces a result similar to:
 681      * <pre>{@code
 682      *     groupingBy(classifier, toList());
 683      * }</pre>
 684      *
 685      * @param <T> the type of the input elements
 686      * @param <K> the type of the keys
 687      * @param classifier the classifier function mapping input elements to keys
 688      * @return a {@code Collector} implementing the group-by operation
 689      *
 690      * @see #groupingBy(Function, Collector)
 691      * @see #groupingBy(Function, Supplier, Collector)
 692      * @see #groupingByConcurrent(Function)
 693      */
 694     public static <T, K> Collector<T, ?, Map<K, List<T>>>
 695     groupingBy(Function<? super T, ? extends K> classifier) {
 696         return groupingBy(classifier, toList());
 697     }
 698 
 699     /**
 700      * Returns a {@code Collector} implementing a cascaded "group by" operation
 701      * on input elements of type {@code T}, grouping elements according to a
 702      * classification function, and then performing a reduction operation on
 703      * the values associated with a given key using the specified downstream
 704      * {@code Collector}.
 705      *
 706      * <p>The classification function maps elements to some key type {@code K}.
 707      * The downstream collector operates on elements of type {@code T} and
 708      * produces a result of type {@code D}. The resulting collector produces a
 709      * {@code Map<K, D>}.
 710      *
 711      * <p>There are no guarantees on the type, mutability,
 712      * serializability, or thread-safety of the {@code Map} returned.
 713      *
 714      * <p>For example, to compute the set of last names of people in each city:
 715      * <pre>{@code
 716      *     Map<City, Set<String>> namesByCity
 717      *         = people.stream().collect(groupingBy(Person::getCity,
 718      *                                              mapping(Person::getLastName, toSet())));
 719      * }</pre>
 720      *
 721      * @param <T> the type of the input elements
 722      * @param <K> the type of the keys
 723      * @param <A> the intermediate accumulation type of the downstream collector
 724      * @param <D> the result type of the downstream reduction
 725      * @param classifier a classifier function mapping input elements to keys
 726      * @param downstream a {@code Collector} implementing the downstream reduction
 727      * @return a {@code Collector} implementing the cascaded group-by operation
 728      * @see #groupingBy(Function)
 729      *
 730      * @see #groupingBy(Function, Supplier, Collector)
 731      * @see #groupingByConcurrent(Function, Collector)
 732      */
 733     public static <T, K, A, D>
 734     Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
 735                                           Collector<? super T, A, D> downstream) {
 736         return groupingBy(classifier, HashMap::new, downstream);
 737     }
 738 
 739     /**
 740      * Returns a {@code Collector} implementing a cascaded "group by" operation
 741      * on input elements of type {@code T}, grouping elements according to a
 742      * classification function, and then performing a reduction operation on
 743      * the values associated with a given key using the specified downstream
 744      * {@code Collector}.  The {@code Map} produced by the Collector is created
 745      * with the supplied factory function.
 746      *
 747      * <p>The classification function maps elements to some key type {@code K}.
 748      * The downstream collector operates on elements of type {@code T} and
 749      * produces a result of type {@code D}. The resulting collector produces a
 750      * {@code Map<K, D>}.
 751      *
 752      * <p>For example, to compute the set of last names of people in each city,
 753      * where the city names are sorted:
 754      * <pre>{@code
 755      *     Map<City, Set<String>> namesByCity
 756      *         = people.stream().collect(groupingBy(Person::getCity, TreeMap::new,
 757      *                                              mapping(Person::getLastName, toSet())));
 758      * }</pre>
 759      *
 760      * @param <T> the type of the input elements
 761      * @param <K> the type of the keys
 762      * @param <A> the intermediate accumulation type of the downstream collector
 763      * @param <D> the result type of the downstream reduction
 764      * @param <M> the type of the resulting {@code Map}
 765      * @param classifier a classifier function mapping input elements to keys
 766      * @param downstream a {@code Collector} implementing the downstream reduction
 767      * @param mapFactory a function which, when called, produces a new empty
 768      *                   {@code Map} of the desired type
 769      * @return a {@code Collector} implementing the cascaded group-by operation
 770      *
 771      * @see #groupingBy(Function, Collector)
 772      * @see #groupingBy(Function)
 773      * @see #groupingByConcurrent(Function, Supplier, Collector)
 774      */
 775     public static <T, K, D, A, M extends Map<K, D>>
 776     Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
 777                                   Supplier<M> mapFactory,
 778                                   Collector<? super T, A, D> downstream) {
 779         Supplier<A> downstreamSupplier = downstream.supplier();
 780         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
 781         BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
 782             K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
 783             A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
 784             downstreamAccumulator.accept(container, t);
 785         };
 786         BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner());
 787         @SuppressWarnings("unchecked")
 788         Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;
 789 
 790         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
 791             return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
 792         }
 793         else {
 794             @SuppressWarnings("unchecked")
 795             Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
 796             Function<Map<K, A>, M> finisher = intermediate -> {
 797                 intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
 798                 @SuppressWarnings("unchecked")
 799                 M castResult = (M) intermediate;
 800                 return castResult;
 801             };
 802             return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
 803         }
 804     }
 805 
 806     /**
 807      * Returns a concurrent {@code Collector} implementing a "group by"
 808      * operation on input elements of type {@code T}, grouping elements
 809      * according to a classification function.
 810      *
 811      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
 812      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
 813      *
 814      * <p>The classification function maps elements to some key type {@code K}.
 815      * The collector produces a {@code ConcurrentMap<K, List<T>>} whose keys are the
 816      * values resulting from applying the classification function to the input
 817      * elements, and whose corresponding values are {@code List}s containing the
 818      * input elements which map to the associated key under the classification
 819      * function.
 820      *
 821      * <p>There are no guarantees on the type, mutability, or serializability
 822      * of the {@code Map} or {@code List} objects returned, or of the
 823      * thread-safety of the {@code List} objects returned.
 824      * @implSpec
 825      * This produces a result similar to:
 826      * <pre>{@code
 827      *     groupingByConcurrent(classifier, toList());
 828      * }</pre>
 829      *
 830      * @param <T> the type of the input elements
 831      * @param <K> the type of the keys
 832      * @param classifier a classifier function mapping input elements to keys
 833      * @return a {@code Collector} implementing the group-by operation
 834      *
 835      * @see #groupingBy(Function)
 836      * @see #groupingByConcurrent(Function, Collector)
 837      * @see #groupingByConcurrent(Function, Supplier, Collector)
 838      */
 839     public static <T, K>
 840     Collector<T, ?, ConcurrentMap<K, List<T>>>
 841     groupingByConcurrent(Function<? super T, ? extends K> classifier) {
 842         return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
 843     }
 844 
 845     /**
 846      * Returns a concurrent {@code Collector} implementing a cascaded "group by"
 847      * operation on input elements of type {@code T}, grouping elements
 848      * according to a classification function, and then performing a reduction
 849      * operation on the values associated with a given key using the specified
 850      * downstream {@code Collector}.
 851      *
 852      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
 853      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
 854      *
 855      * <p>The classification function maps elements to some key type {@code K}.
 856      * The downstream collector operates on elements of type {@code T} and
 857      * produces a result of type {@code D}. The resulting collector produces a
 858      * {@code Map<K, D>}.
 859      *
 860      * <p>For example, to compute the set of last names of people in each city,
 861      * where the city names are sorted:
 862      * <pre>{@code
 863      *     ConcurrentMap<City, Set<String>> namesByCity
 864      *         = people.stream().collect(groupingByConcurrent(Person::getCity, ConcurrentSkipListMap::new,
 865      *                                                        mapping(Person::getLastName, toSet())));
 866      * }</pre>
 867      *
 868      * @param <T> the type of the input elements
 869      * @param <K> the type of the keys
 870      * @param <A> the intermediate accumulation type of the downstream collector
 871      * @param <D> the result type of the downstream reduction
 872      * @param classifier a classifier function mapping input elements to keys
 873      * @param downstream a {@code Collector} implementing the downstream reduction
 874      * @return a {@code Collector} implementing the cascaded group-by operation
 875      *
 876      * @see #groupingBy(Function, Collector)
 877      * @see #groupingByConcurrent(Function)
 878      * @see #groupingByConcurrent(Function, Supplier, Collector)
 879      */
 880     public static <T, K, A, D>
 881     Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier,
 882                                                               Collector<? super T, A, D> downstream) {
 883         return groupingByConcurrent(classifier, ConcurrentHashMap::new, downstream);
 884     }
 885 
 886     /**
 887      * Returns a concurrent {@code Collector} implementing a cascaded "group by"
 888      * operation on input elements of type {@code T}, grouping elements
 889      * according to a classification function, and then performing a reduction
 890      * operation on the values associated with a given key using the specified
 891      * downstream {@code Collector}.  The {@code ConcurrentMap} produced by the
 892      * Collector is created with the supplied factory function.
 893      *
 894      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
 895      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
 896      *
 897      * <p>The classification function maps elements to some key type {@code K}.
 898      * The downstream collector operates on elements of type {@code T} and
 899      * produces a result of type {@code D}. The resulting collector produces a
 900      * {@code Map<K, D>}.
 901      *
 902      * <p>For example, to compute the set of last names of people in each city,
 903      * where the city names are sorted:
 904      * <pre>{@code
 905      *     ConcurrentMap<City, Set<String>> namesByCity
 906      *         = people.stream().collect(groupingBy(Person::getCity, ConcurrentSkipListMap::new,
 907      *                                              mapping(Person::getLastName, toSet())));
 908      * }</pre>
 909      *
 910      *
 911      * @param <T> the type of the input elements
 912      * @param <K> the type of the keys
 913      * @param <A> the intermediate accumulation type of the downstream collector
 914      * @param <D> the result type of the downstream reduction
 915      * @param <M> the type of the resulting {@code ConcurrentMap}
 916      * @param classifier a classifier function mapping input elements to keys
 917      * @param downstream a {@code Collector} implementing the downstream reduction
 918      * @param mapFactory a function which, when called, produces a new empty
 919      *                   {@code ConcurrentMap} of the desired type
 920      * @return a {@code Collector} implementing the cascaded group-by operation
 921      *
 922      * @see #groupingByConcurrent(Function)
 923      * @see #groupingByConcurrent(Function, Collector)
 924      * @see #groupingBy(Function, Supplier, Collector)
 925      */
 926     public static <T, K, A, D, M extends ConcurrentMap<K, D>>
 927     Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier,
 928                                             Supplier<M> mapFactory,
 929                                             Collector<? super T, A, D> downstream) {
 930         Supplier<A> downstreamSupplier = downstream.supplier();
 931         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
 932         BinaryOperator<ConcurrentMap<K, A>> merger = Collectors.<K, A, ConcurrentMap<K, A>>mapMerger(downstream.combiner());
 933         @SuppressWarnings("unchecked")
 934         Supplier<ConcurrentMap<K, A>> mangledFactory = (Supplier<ConcurrentMap<K, A>>) mapFactory;
 935         BiConsumer<ConcurrentMap<K, A>, T> accumulator;
 936         if (downstream.characteristics().contains(Collector.Characteristics.CONCURRENT)) {
 937             accumulator = (m, t) -> {
 938                 K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
 939                 A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
 940                 downstreamAccumulator.accept(resultContainer, t);
 941             };
 942         }
 943         else {
 944             accumulator = (m, t) -> {
 945                 K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
 946                 A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
 947                 synchronized (resultContainer) {
 948                     downstreamAccumulator.accept(resultContainer, t);
 949                 }
 950             };
 951         }
 952 
 953         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
 954             return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_CONCURRENT_ID);
 955         }
 956         else {
 957             @SuppressWarnings("unchecked")
 958             Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
 959             Function<ConcurrentMap<K, A>, M> finisher = intermediate -> {
 960                 intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
 961                 @SuppressWarnings("unchecked")
 962                 M castResult = (M) intermediate;
 963                 return castResult;
 964             };
 965             return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID);
 966         }
 967     }
 968 
 969     /**
 970      * Returns a {@code Collector} which partitions the input elements according
 971      * to a {@code Predicate}, and organizes them into a
 972      * {@code Map<Boolean, List<T>>}.
 973      *
 974      * There are no guarantees on the type, mutability,
 975      * serializability, or thread-safety of the {@code Map} returned.
 976      *
 977      * @param <T> the type of the input elements
 978      * @param predicate a predicate used for classifying input elements
 979      * @return a {@code Collector} implementing the partitioning operation
 980      *
 981      * @see #partitioningBy(Predicate, Collector)
 982      */
 983     public static <T>
 984     Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
 985         return partitioningBy(predicate, toList());
 986     }
 987 
 988     /**
 989      * Returns a {@code Collector} which partitions the input elements according
 990      * to a {@code Predicate}, reduces the values in each partition according to
 991      * another {@code Collector}, and organizes them into a
 992      * {@code Map<Boolean, D>} whose values are the result of the downstream
 993      * reduction.
 994      *
 995      * <p>There are no guarantees on the type, mutability,
 996      * serializability, or thread-safety of the {@code Map} returned.
 997      *
 998      * @param <T> the type of the input elements
 999      * @param <A> the intermediate accumulation type of the downstream collector
1000      * @param <D> the result type of the downstream reduction
1001      * @param predicate a predicate used for classifying input elements
1002      * @param downstream a {@code Collector} implementing the downstream
1003      *                   reduction
1004      * @return a {@code Collector} implementing the cascaded partitioning
1005      *         operation
1006      *
1007      * @see #partitioningBy(Predicate)
1008      */
1009     public static <T, D, A>
1010     Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
1011                                                     Collector<? super T, A, D> downstream) {
1012         @SuppressWarnings("unchecked")
1013         BiConsumer<D, ? super T> downstreamAccumulator = (BiConsumer<D, ? super T>) downstream.accumulator();
1014         BiConsumer<Map<Boolean, A>, T> accumulator = (result, t) -> {
1015             Partition<D> asPartition = ((Partition<D>) result);
1016             downstreamAccumulator.accept(predicate.test(t) ? asPartition.forTrue : asPartition.forFalse, t);
1017         };
1018         BinaryOperator<A> op = downstream.combiner();
1019         BinaryOperator<Map<Boolean, A>> merger = (m1, m2) -> {
1020             Partition<A> left = (Partition<A>) m1;
1021             Partition<A> right = (Partition<A>) m2;
1022             return new Partition<>(op.apply(left.forTrue, right.forTrue),
1023                                    op.apply(left.forFalse, right.forFalse));
1024         };
1025         Supplier<Map<Boolean, A>> supplier = () -> new Partition<>(downstream.supplier().get(),
1026                                                                    downstream.supplier().get());
1027         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
1028             return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
1029         }
1030         else {
1031             Function<Map<Boolean, A>, Map<Boolean, D>> finisher = (Map<Boolean, A> par) -> {
1032                 Partition<A> asAPartition = (Partition<A>) par;
1033                 return new Partition<>(downstream.finisher().apply(asAPartition.forTrue),
1034                                        downstream.finisher().apply(asAPartition.forFalse));
1035             };
1036             return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
1037         }
1038     }
1039 
1040     /**
1041      * Returns a {@code Collector} that accumulate elements into a
1042      * {@code Map} whose keys and values are the result of applying the provided
1043      * mapping functions to the input elements.
1044      *
1045      * <p>If the mapped keys contains duplicates (according to
1046      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1047      * thrown when the collection operation is performed.  If the mapped keys
1048      * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
1049      * instead.
1050      *
1051      * @apiNote
1052      * It is common for either the key or the value to be the input elements.
1053      * In this case, the utility method
1054      * {@link java.util.function.Function#identity()} may be helpful.
1055      * For example, the following produces a {@code Map} mapping
1056      * students to their grade point average:
1057      * <pre>{@code
1058      *     Map<Student, Double> studentToGPA
1059      *         students.stream().collect(toMap(Functions.identity(),
1060      *                                         student -> computeGPA(student)));
1061      * }</pre>
1062      * And the following produces a {@code Map} mapping a unique identifier to
1063      * students:
1064      * <pre>{@code
1065      *     Map<String, Student> studentIdToStudent
1066      *         students.stream().collect(toMap(Student::getId,
1067      *                                         Functions.identity());
1068      * }</pre>
1069      *
1070      * @param <T> the type of the input elements
1071      * @param <K> the output type of the key mapping function
1072      * @param <U> the output type of the value mapping function
1073      * @param keyMapper a mapping function to produce keys
1074      * @param valueMapper a mapping function to produce values
1075      * @return a {@code Collector} which collects elements into a {@code Map}
1076      * whose keys and values are the result of applying mapping functions to
1077      * the input elements
1078      *
1079      * @see #toMap(Function, Function, BinaryOperator)
1080      * @see #toMap(Function, Function, BinaryOperator, Supplier)
1081      * @see #toConcurrentMap(Function, Function)
1082      */
1083     public static <T, K, U>
1084     Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
1085                                     Function<? super T, ? extends U> valueMapper) {
1086         return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
1087     }
1088 
1089     /**
1090      * Returns a {@code Collector} that accumulate elements into a
1091      * {@code Map} whose keys and values are the result of applying the provided
1092      * mapping functions to the input elements.
1093      *
1094      * <p>If the mapped
1095      * keys contains duplicates (according to {@link Object#equals(Object)}),
1096      * the value mapping function is applied to each equal element, and the
1097      * results are merged using the provided merging function.
1098      *
1099      * @apiNote
1100      * There are multiple ways to deal with collisions between multiple elements
1101      * mapping to the same key.  The other forms of {@code toMap} simply use
1102      * a merge function that throws unconditionally, but you can easily write
1103      * more flexible merge policies.  For example, if you have a stream
1104      * of {@code Person}, and you want to produce a "phone book" mapping name to
1105      * address, but it is possible that two persons have the same name, you can
1106      * do as follows to gracefully deals with these collisions, and produce a
1107      * {@code Map} mapping names to a concatenated list of addresses:
1108      * <pre>{@code
1109      *     Map<String, String> phoneBook
1110      *         people.stream().collect(toMap(Person::getName,
1111      *                                       Person::getAddress,
1112      *                                       (s, a) -> s + ", " + a));
1113      * }</pre>
1114      *
1115      * @param <T> the type of the input elements
1116      * @param <K> the output type of the key mapping function
1117      * @param <U> the output type of the value mapping function
1118      * @param keyMapper a mapping function to produce keys
1119      * @param valueMapper a mapping function to produce values
1120      * @param mergeFunction a merge function, used to resolve collisions between
1121      *                      values associated with the same key, as supplied
1122      *                      to {@link Map#merge(Object, Object, BiFunction)}
1123      * @return a {@code Collector} which collects elements into a {@code Map}
1124      * whose keys are the result of applying a key mapping function to the input
1125      * elements, and whose values are the result of applying a value mapping
1126      * function to all input elements equal to the key and combining them
1127      * using the merge function
1128      *
1129      * @see #toMap(Function, Function)
1130      * @see #toMap(Function, Function, BinaryOperator, Supplier)
1131      * @see #toConcurrentMap(Function, Function, BinaryOperator)
1132      */
1133     public static <T, K, U>
1134     Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
1135                                     Function<? super T, ? extends U> valueMapper,
1136                                     BinaryOperator<U> mergeFunction) {
1137         return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
1138     }
1139 
1140     /**
1141      * Returns a {@code Collector} that accumulate elements into a
1142      * {@code Map} whose keys and values are the result of applying the provided
1143      * mapping functions to the input elements.
1144      *
1145      * <p>If the mapped
1146      * keys contains duplicates (according to {@link Object#equals(Object)}),
1147      * the value mapping function is applied to each equal element, and the
1148      * results are merged using the provided merging function.  The {@code Map}
1149      * is created by a provided supplier function.
1150      *
1151      * @param <T> the type of the input elements
1152      * @param <K> the output type of the key mapping function
1153      * @param <U> the output type of the value mapping function
1154      * @param <M> the type of the resulting {@code Map}
1155      * @param keyMapper a mapping function to produce keys
1156      * @param valueMapper a mapping function to produce values
1157      * @param mergeFunction a merge function, used to resolve collisions between
1158      *                      values associated with the same key, as supplied
1159      *                      to {@link Map#merge(Object, Object, BiFunction)}
1160      * @param mapSupplier a function which returns a new, empty {@code Map} into
1161      *                    which the results will be inserted
1162      * @return a {@code Collector} which collects elements into a {@code Map}
1163      * whose keys are the result of applying a key mapping function to the input
1164      * elements, and whose values are the result of applying a value mapping
1165      * function to all input elements equal to the key and combining them
1166      * using the merge function
1167      *
1168      * @see #toMap(Function, Function)
1169      * @see #toMap(Function, Function, BinaryOperator)
1170      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
1171      */
1172     public static <T, K, U, M extends Map<K, U>>
1173     Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
1174                                 Function<? super T, ? extends U> valueMapper,
1175                                 BinaryOperator<U> mergeFunction,
1176                                 Supplier<M> mapSupplier) {
1177         BiConsumer<M, T> accumulator
1178                 = (map, element) -> map.merge(keyMapper.apply(element),
1179                                               valueMapper.apply(element), mergeFunction);
1180         return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
1181     }
1182 
1183     /**
1184      * Returns a {@code Collector} that accumulate elements into a
1185      * {@code ConcurrentMap} whose keys and values are the result of applying
1186      * the provided mapping functions to the input elements.
1187      *
1188      * <p>If the mapped keys contains duplicates (according to
1189      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1190      * thrown when the collection operation is performed.  If the mapped keys
1191      * may have duplicates, use
1192      * {@link #toConcurrentMap(Function, Function, BinaryOperator)} instead.
1193      *
1194      * @apiNote
1195      * It is common for either the key or the value to be the input elements.
1196      * In this case, the utility method
1197      * {@link java.util.function.Function#identity()} may be helpful.
1198      * For example, the following produces a {@code Map} mapping
1199      * students to their grade point average:
1200      * <pre>{@code
1201      *     Map<Student, Double> studentToGPA
1202      *         students.stream().collect(toMap(Functions.identity(),
1203      *                                         student -> computeGPA(student)));
1204      * }</pre>
1205      * And the following produces a {@code Map} mapping a unique identifier to
1206      * students:
1207      * <pre>{@code
1208      *     Map<String, Student> studentIdToStudent
1209      *         students.stream().collect(toConcurrentMap(Student::getId,
1210      *                                                   Functions.identity());
1211      * }</pre>
1212      *
1213      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1214      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1215      *
1216      * @param <T> the type of the input elements
1217      * @param <K> the output type of the key mapping function
1218      * @param <U> the output type of the value mapping function
1219      * @param keyMapper the mapping function to produce keys
1220      * @param valueMapper the mapping function to produce values
1221      * @return a concurrent {@code Collector} which collects elements into a
1222      * {@code ConcurrentMap} whose keys are the result of applying a key mapping
1223      * function to the input elements, and whose values are the result of
1224      * applying a value mapping function to the input elements
1225      *
1226      * @see #toMap(Function, Function)
1227      * @see #toConcurrentMap(Function, Function, BinaryOperator)
1228      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
1229      */
1230     public static <T, K, U>
1231     Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
1232                                                         Function<? super T, ? extends U> valueMapper) {
1233         return toConcurrentMap(keyMapper, valueMapper, throwingMerger(), ConcurrentHashMap::new);
1234     }
1235 
1236     /**
1237      * Returns a {@code Collector} that accumulate elements into a
1238      * {@code ConcurrentMap} whose keys and values are the result of applying
1239      * the provided mapping functions to the input elements.
1240      *
1241      * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}),
1242      * the value mapping function is applied to each equal element, and the
1243      * results are merged using the provided merging function.
1244      *
1245      * @apiNote
1246      * There are multiple ways to deal with collisions between multiple elements
1247      * mapping to the same key.  The other forms of {@code toConcurrentMap} simply use
1248      * a merge function that throws unconditionally, but you can easily write
1249      * more flexible merge policies.  For example, if you have a stream
1250      * of {@code Person}, and you want to produce a "phone book" mapping name to
1251      * address, but it is possible that two persons have the same name, you can
1252      * do as follows to gracefully deals with these collisions, and produce a
1253      * {@code Map} mapping names to a concatenated list of addresses:
1254      * <pre>{@code
1255      *     Map<String, String> phoneBook
1256      *         people.stream().collect(toConcurrentMap(Person::getName,
1257      *                                                 Person::getAddress,
1258      *                                                 (s, a) -> s + ", " + a));
1259      * }</pre>
1260      *
1261      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1262      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1263      *
1264      * @param <T> the type of the input elements
1265      * @param <K> the output type of the key mapping function
1266      * @param <U> the output type of the value mapping function
1267      * @param keyMapper a mapping function to produce keys
1268      * @param valueMapper a mapping function to produce values
1269      * @param mergeFunction a merge function, used to resolve collisions between
1270      *                      values associated with the same key, as supplied
1271      *                      to {@link Map#merge(Object, Object, BiFunction)}
1272      * @return a concurrent {@code Collector} which collects elements into a
1273      * {@code ConcurrentMap} whose keys are the result of applying a key mapping
1274      * function to the input elements, and whose values are the result of
1275      * applying a value mapping function to all input elements equal to the key
1276      * and combining them using the merge function
1277      *
1278      * @see #toConcurrentMap(Function, Function)
1279      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
1280      * @see #toMap(Function, Function, BinaryOperator)
1281      */
1282     public static <T, K, U>
1283     Collector<T, ?, ConcurrentMap<K,U>>
1284     toConcurrentMap(Function<? super T, ? extends K> keyMapper,
1285                     Function<? super T, ? extends U> valueMapper,
1286                     BinaryOperator<U> mergeFunction) {
1287         return toConcurrentMap(keyMapper, valueMapper, mergeFunction, ConcurrentHashMap::new);
1288     }
1289 
1290     /**
1291      * Returns a {@code Collector} that accumulate elements into a
1292      * {@code ConcurrentMap} whose keys and values are the result of applying
1293      * the provided mapping functions to the input elements.
1294      *
1295      * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}),
1296      * the value mapping function is applied to each equal element, and the
1297      * results are merged using the provided merging function.  The
1298      * {@code ConcurrentMap} is created by a provided supplier function.
1299      *
1300      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1301      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1302      *
1303      * @param <T> the type of the input elements
1304      * @param <K> the output type of the key mapping function
1305      * @param <U> the output type of the value mapping function
1306      * @param <M> the type of the resulting {@code ConcurrentMap}
1307      * @param keyMapper a mapping function to produce keys
1308      * @param valueMapper a mapping function to produce values
1309      * @param mergeFunction a merge function, used to resolve collisions between
1310      *                      values associated with the same key, as supplied
1311      *                      to {@link Map#merge(Object, Object, BiFunction)}
1312      * @param mapSupplier a function which returns a new, empty {@code Map} into
1313      *                    which the results will be inserted
1314      * @return a concurrent {@code Collector} which collects elements into a
1315      * {@code ConcurrentMap} whose keys are the result of applying a key mapping
1316      * function to the input elements, and whose values are the result of
1317      * applying a value mapping function to all input elements equal to the key
1318      * and combining them using the merge function
1319      *
1320      * @see #toConcurrentMap(Function, Function)
1321      * @see #toConcurrentMap(Function, Function, BinaryOperator)
1322      * @see #toMap(Function, Function, BinaryOperator, Supplier)
1323      */
1324     public static <T, K, U, M extends ConcurrentMap<K, U>>
1325     Collector<T, ?, M> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
1326                                        Function<? super T, ? extends U> valueMapper,
1327                                        BinaryOperator<U> mergeFunction,
1328                                        Supplier<M> mapSupplier) {
1329         BiConsumer<M, T> accumulator
1330                 = (map, element) -> map.merge(keyMapper.apply(element),
1331                                               valueMapper.apply(element), mergeFunction);
1332         return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_CONCURRENT_ID);
1333     }
1334 
1335     /**
1336      * Returns a {@code Collector} which applies an {@code int}-producing
1337      * mapping function to each input element, and returns summary statistics
1338      * for the resulting values.
1339      *
1340      * @param <T> the type of the input elements
1341      * @param mapper a mapping function to apply to each element
1342      * @return a {@code Collector} implementing the summary-statistics reduction
1343      *
1344      * @see #summarizingDouble(ToDoubleFunction)
1345      * @see #summarizingLong(ToLongFunction)
1346      */
1347     public static <T>
1348     Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) {
1349         return new CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>(
1350                 IntSummaryStatistics::new,
1351                 (r, t) -> r.accept(mapper.applyAsInt(t)),
1352                 (l, r) -> { l.combine(r); return l; }, CH_ID);
1353     }
1354 
1355     /**
1356      * Returns a {@code Collector} which applies an {@code long}-producing
1357      * mapping function to each input element, and returns summary statistics
1358      * for the resulting values.
1359      *
1360      * @param <T> the type of the input elements
1361      * @param mapper the mapping function to apply to each element
1362      * @return a {@code Collector} implementing the summary-statistics reduction
1363      *
1364      * @see #summarizingDouble(ToDoubleFunction)
1365      * @see #summarizingInt(ToIntFunction)
1366      */
1367     public static <T>
1368     Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) {
1369         return new CollectorImpl<T, LongSummaryStatistics, LongSummaryStatistics>(
1370                 LongSummaryStatistics::new,
1371                 (r, t) -> r.accept(mapper.applyAsLong(t)),
1372                 (l, r) -> { l.combine(r); return l; }, CH_ID);
1373     }
1374 
1375     /**
1376      * Returns a {@code Collector} which applies an {@code double}-producing
1377      * mapping function to each input element, and returns summary statistics
1378      * for the resulting values.
1379      *
1380      * @param <T> the type of the input elements
1381      * @param mapper a mapping function to apply to each element
1382      * @return a {@code Collector} implementing the summary-statistics reduction
1383      *
1384      * @see #summarizingLong(ToLongFunction)
1385      * @see #summarizingInt(ToIntFunction)
1386      */
1387     public static <T>
1388     Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) {
1389         return new CollectorImpl<T, DoubleSummaryStatistics, DoubleSummaryStatistics>(
1390                 DoubleSummaryStatistics::new,
1391                 (r, t) -> r.accept(mapper.applyAsDouble(t)),
1392                 (l, r) -> { l.combine(r); return l; }, CH_ID);
1393     }
1394 
1395     /**
1396      * Implementation class used by partitioningBy.
1397      */
1398     private static final class Partition<T>
1399             extends AbstractMap<Boolean, T>
1400             implements Map<Boolean, T> {
1401         final T forTrue;
1402         final T forFalse;
1403 
1404         Partition(T forTrue, T forFalse) {
1405             this.forTrue = forTrue;
1406             this.forFalse = forFalse;
1407         }
1408 
1409         @Override
1410         public Set<Map.Entry<Boolean, T>> entrySet() {
1411             return new AbstractSet<Map.Entry<Boolean, T>>() {
1412                 @Override
1413                 public Iterator<Map.Entry<Boolean, T>> iterator() {
1414                     Map.Entry<Boolean, T> falseEntry = new SimpleImmutableEntry<>(false, forFalse);
1415                     Map.Entry<Boolean, T> trueEntry = new SimpleImmutableEntry<>(true, forTrue);
1416                     return Arrays.asList(falseEntry, trueEntry).iterator();
1417                 }
1418 
1419                 @Override
1420                 public int size() {
1421                     return 2;
1422                 }
1423             };
1424         }
1425     }
1426 }