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