1 /*
2  * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */

25 package java.util.stream;
26
27 import java.util.AbstractMap;
28 import java.util.AbstractSet;
29 import java.util.ArrayList;
30 import java.util.Collection;
31 import java.util.Collections;
32 import java.util.Comparator;
33 import java.util.DoubleSummaryStatistics;
34 import java.util.EnumSet;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.IntSummaryStatistics;
38 import java.util.Iterator;
39 import java.util.List;
40 import java.util.LongSummaryStatistics;
41 import java.util.Map;
42 import java.util.Objects;
43 import java.util.Optional;
44 import java.util.Set;
45 import java.util.StringJoiner;
46 import java.util.concurrent.ConcurrentHashMap;
47 import java.util.concurrent.ConcurrentMap;
48 import java.util.function.BiConsumer;
49 import java.util.function.BiFunction;
50 import java.util.function.BinaryOperator;
51 import java.util.function.Consumer;
52 import java.util.function.Function;
53 import java.util.function.Predicate;
54 import java.util.function.Supplier;
55 import java.util.function.ToDoubleFunction;
56 import java.util.function.ToIntFunction;
57 import java.util.function.ToLongFunction;
58
59 /**
60  * Implementations of {@link Collector} that implement various useful reduction
61  * operations, such as accumulating elements into collections, summarizing
62  * elements according to various criteria, etc.
63  *
64  * <p>The following are examples of using the predefined collectors to perform
65  * common mutable reduction tasks:
66  *
67  * <pre>{@code
68  * // Accumulate names into a List
69  * List<String> list = people.stream()
70  *   .map(Person::getName)
71  *   .collect(Collectors.toList());
72  *
73  * // Accumulate names into a TreeSet
74  * Set<String> set = people.stream()
75  *   .map(Person::getName)
76  *   .collect(Collectors.toCollection(TreeSet::new));
77  *
78  * // Convert elements to strings and concatenate them, separated by commas
79  * String joined = things.stream()
80  *   .map(Object::toString)
81  *   .collect(Collectors.joining(", "));
82  *
83  * // Compute sum of salaries of employee
84  * int total = employees.stream()
85  *   .collect(Collectors.summingInt(Employee::getSalary));
86  *
87  * // Group employees by department
88  * Map<Department, List<Employee>> byDept = employees.stream()
89  *   .collect(Collectors.groupingBy(Employee::getDepartment));
90  *
91  * // Compute sum of salaries by department
92  * Map<Department, Integer> totalByDept = employees.stream()
93  *   .collect(Collectors.groupingBy(Employee::getDepartment,
94  *                                  Collectors.summingInt(Employee::getSalary)));
95  *
96  * // Partition students into passing and failing
97  * Map<Boolean, List<Student>> passingFailing = students.stream()
98  *   .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
99  *
100  * }</pre>
101  *
102  * @since 1.8
103  */

104 public final class Collectors {
105
106     static final Set<Collector.Characteristics> CH_CONCURRENT_ID
107             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
108                                                      Collector.Characteristics.UNORDERED,
109                                                      Collector.Characteristics.IDENTITY_FINISH));
110     static final Set<Collector.Characteristics> CH_CONCURRENT_NOID
111             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
112                                                      Collector.Characteristics.UNORDERED));
113     static final Set<Collector.Characteristics> CH_ID
114             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
115     static final Set<Collector.Characteristics> CH_UNORDERED_ID
116             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
117                                                      Collector.Characteristics.IDENTITY_FINISH));
118     static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
119     static final Set<Collector.Characteristics> CH_UNORDERED_NOID
120             = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED));
121
122     private Collectors() { }
123
124     /**
125      * Construct an {@code IllegalStateException} with appropriate message.
126      *
127      * @param k the duplicate key
128      * @param u 1st value to be accumulated/merged
129      * @param v 2nd value to be accumulated/merged
130      */

131     private static IllegalStateException duplicateKeyException(
132             Object k, Object u, Object v) {
133         return new IllegalStateException(String.format(
134             "Duplicate key %s (attempted merging values %s and %s)",
135             k, u, v));
136     }
137
138     /**
139      * {@code BinaryOperator<Map>} that merges the contents of its right
140      * argument into its left argument, throwing {@code IllegalStateException}
141      * if duplicate keys are encountered.
142      *
143      * @param <K> type of the map keys
144      * @param <V> type of the map values
145      * @param <M> type of the map
146      * @return a merge function for two maps
147      */

148     private static <K, V, M extends Map<K,V>>
149     BinaryOperator<M> uniqKeysMapMerger() {
150         return (m1, m2) -> {
151             for (Map.Entry<K,V> e : m2.entrySet()) {
152                 K k = e.getKey();
153                 V v = Objects.requireNonNull(e.getValue());
154                 V u = m1.putIfAbsent(k, v);
155                 if (u != nullthrow duplicateKeyException(k, u, v);
156             }
157             return m1;
158         };
159     }
160
161     /**
162      * {@code BiConsumer<Map, T>} that accumulates (key, value) pairs
163      * extracted from elements into the map, throwing {@code IllegalStateException}
164      * if duplicate keys are encountered.
165      *
166      * @param keyMapper a function that maps an element into a key
167      * @param valueMapper a function that maps an element into a value
168      * @param <T> type of elements
169      * @param <K> type of map keys
170      * @param <V> type of map values
171      * @return an accumulating consumer
172      */

173     private static <T, K, V>
174     BiConsumer<Map<K, V>, T> uniqKeysMapAccumulator(Function<? super T, ? extends K> keyMapper,
175                                                     Function<? super T, ? extends V> valueMapper) {
176         return (map, element) -> {
177             K k = keyMapper.apply(element);
178             V v = Objects.requireNonNull(valueMapper.apply(element));
179             V u = map.putIfAbsent(k, v);
180             if (u != nullthrow duplicateKeyException(k, u, v);
181         };
182     }
183
184     @SuppressWarnings("unchecked")
185     private static <I, R> Function<I, R> castingIdentity() {
186         return i -> (R) i;
187     }
188
189     /**
190      * Simple implementation class for {@code Collector}.
191      *
192      * @param <T> the type of elements to be collected
193      * @param <R> the type of the result
194      */

195     static class CollectorImpl<T, A, R> implements Collector<T, A, R> {
196         private final Supplier<A> supplier;
197         private final BiConsumer<A, T> accumulator;
198         private final BinaryOperator<A> combiner;
199         private final Function<A, R> finisher;
200         private final Set<Characteristics> characteristics;
201
202         CollectorImpl(Supplier<A> supplier,
203                       BiConsumer<A, T> accumulator,
204                       BinaryOperator<A> combiner,
205                       Function<A,R> finisher,
206                       Set<Characteristics> characteristics) {
207             this.supplier = supplier;
208             this.accumulator = accumulator;
209             this.combiner = combiner;
210             this.finisher = finisher;
211             this.characteristics = characteristics;
212         }
213
214         CollectorImpl(Supplier<A> supplier,
215                       BiConsumer<A, T> accumulator,
216                       BinaryOperator<A> combiner,
217                       Set<Characteristics> characteristics) {
218             this(supplier, accumulator, combiner, castingIdentity(), characteristics);
219         }
220
221         @Override
222         public BiConsumer<A, T> accumulator() {
223             return accumulator;
224         }
225
226         @Override
227         public Supplier<A> supplier() {
228             return supplier;
229         }
230
231         @Override
232         public BinaryOperator<A> combiner() {
233             return combiner;
234         }
235
236         @Override
237         public Function<A, R> finisher() {
238             return finisher;
239         }
240
241         @Override
242         public Set<Characteristics> characteristics() {
243             return characteristics;
244         }
245     }
246
247     /**
248      * Returns a {@code Collector} that accumulates the input elements into a
249      * new {@code Collection}, in encounter order.  The {@code Collection} is
250      * created by the provided factory.
251      *
252      * @param <T> the type of the input elements
253      * @param <C> the type of the resulting {@code Collection}
254      * @param collectionFactory a supplier providing a new empty {@code Collection}
255      *                          into which the results will be inserted
256      * @return a {@code Collector} which collects all the input elements into a
257      * {@code Collection}, in encounter order
258      */

259     public static <T, C extends Collection<T>>
260     Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
261         return new CollectorImpl<>(collectionFactory, Collection<T>::add,
262                                    (r1, r2) -> { r1.addAll(r2); return r1; },
263                                    CH_ID);
264     }
265
266     /**
267      * Returns a {@code Collector} that accumulates the input elements into a
268      * new {@code List}. There are no guarantees on the type, mutability,
269      * serializability, or thread-safety of the {@code List} returned; if more
270      * control over the returned {@code List} is required, use {@link #toCollection(Supplier)}.
271      *
272      * @param <T> the type of the input elements
273      * @return a {@code Collector} which collects all the input elements into a
274      * {@code List}, in encounter order
275      */

276     public static <T>
277     Collector<T, ?, List<T>> toList() {
278         return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
279                                    (left, right) -> { left.addAll(right); return left; },
280                                    CH_ID);
281     }
282
283     /**
284      * Returns a {@code Collector} that accumulates the input elements into an
285      * <a href="../List.html#unmodifiable">unmodifiable List</a> in encounter
286      * order. The returned Collector disallows null values and will throw
287      * {@code NullPointerException} if it is presented with a null value.
288      *
289      * @param <T> the type of the input elements
290      * @return a {@code Collector} that accumulates the input elements into an
291      * <a href="../List.html#unmodifiable">unmodifiable List</a> in encounter order
292      * @since 10
293      */

294     @SuppressWarnings("unchecked")
295     public static <T>
296     Collector<T, ?, List<T>> toUnmodifiableList() {
297         return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
298                                    (left, right) -> { left.addAll(right); return left; },
299                                    list -> (List<T>)List.of(list.toArray()),
300                                    CH_NOID);
301     }
302
303     /**
304      * Returns a {@code Collector} that accumulates the input elements into a
305      * new {@code Set}. There are no guarantees on the type, mutability,
306      * serializability, or thread-safety of the {@code Set} returned; if more
307      * control over the returned {@code Set} is required, use
308      * {@link #toCollection(Supplier)}.
309      *
310      * <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
311      * Collector.
312      *
313      * @param <T> the type of the input elements
314      * @return a {@code Collector} which collects all the input elements into a
315      * {@code Set}
316      */

317     public static <T>
318     Collector<T, ?, Set<T>> toSet() {
319         return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
320                                    (left, right) -> {
321                                        if (left.size() < right.size()) {
322                                            right.addAll(left); return right;
323                                        } else {
324                                            left.addAll(right); return left;
325                                        }
326                                    },
327                                    CH_UNORDERED_ID);
328     }
329
330     /**
331      * Returns a {@code Collector} that accumulates the input elements into an
332      * <a href="../Set.html#unmodifiable">unmodifiable Set</a>. The returned
333      * Collector disallows null values and will throw {@code NullPointerException}
334      * if it is presented with a null value. If the input contains duplicate elements,
335      * an arbitrary element of the duplicates is preserved.
336      *
337      * <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
338      * Collector.
339      *
340      * @param <T> the type of the input elements
341      * @return a {@code Collector} that accumulates the input elements into an
342      * <a href="../Set.html#unmodifiable">unmodifiable Set</a>
343      * @since 10
344      */

345     @SuppressWarnings("unchecked")
346     public static <T>
347     Collector<T, ?, Set<T>> toUnmodifiableSet() {
348         return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
349                                    (left, right) -> {
350                                        if (left.size() < right.size()) {
351                                            right.addAll(left); return right;
352                                        } else {
353                                            left.addAll(right); return left;
354                                        }
355                                    },
356                                    set -> (Set<T>)Set.of(set.toArray()),
357                                    CH_UNORDERED_NOID);
358     }
359
360     /**
361      * Returns a {@code Collector} that concatenates the input elements into a
362      * {@code String}, in encounter order.
363      *
364      * @return a {@code Collector} that concatenates the input elements into a
365      * {@code String}, in encounter order
366      */

367     public static Collector<CharSequence, ?, String> joining() {
368         return new CollectorImpl<CharSequence, StringBuilder, String>(
369                 StringBuilder::new, StringBuilder::append,
370                 (r1, r2) -> { r1.append(r2); return r1; },
371                 StringBuilder::toString, CH_NOID);
372     }
373
374     /**
375      * Returns a {@code Collector} that concatenates the input elements,
376      * separated by the specified delimiter, in encounter order.
377      *
378      * @param delimiter the delimiter to be used between each element
379      * @return A {@code Collector} which concatenates CharSequence elements,
380      * separated by the specified delimiter, in encounter order
381      */

382     public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {
383         return joining(delimiter, """");
384     }
385
386     /**
387      * Returns a {@code Collector} that concatenates the input elements,
388      * separated by the specified delimiter, with the specified prefix and
389      * suffix, in encounter order.
390      *
391      * @param delimiter the delimiter to be used between each element
392      * @param  prefix the sequence of characters to be used at the beginning
393      *                of the joined result
394      * @param  suffix the sequence of characters to be used at the end
395      *                of the joined result
396      * @return A {@code Collector} which concatenates CharSequence elements,
397      * separated by the specified delimiter, in encounter order
398      */

399     public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
400                                                              CharSequence prefix,
401                                                              CharSequence suffix) {
402         return new CollectorImpl<>(
403                 () -> new StringJoiner(delimiter, prefix, suffix),
404                 StringJoiner::add, StringJoiner::merge,
405                 StringJoiner::toString, CH_NOID);
406     }
407
408     /**
409      * {@code BinaryOperator<Map>} that merges the contents of its right
410      * argument into its left argument, using the provided merge function to
411      * handle duplicate keys.
412      *
413      * @param <K> type of the map keys
414      * @param <V> type of the map values
415      * @param <M> type of the map
416      * @param mergeFunction A merge function suitable for
417      * {@link Map#merge(Object, Object, BiFunction) Map.merge()}
418      * @return a merge function for two maps
419      */

420     private static <K, V, M extends Map<K,V>>
421     BinaryOperator<M> mapMerger(BinaryOperator<V> mergeFunction) {
422         return (m1, m2) -> {
423             for (Map.Entry<K,V> e : m2.entrySet())
424                 m1.merge(e.getKey(), e.getValue(), mergeFunction);
425             return m1;
426         };
427     }
428
429     /**
430      * Adapts a {@code Collector} accepting elements of type {@code U} to one
431      * accepting elements of type {@code T} by applying a mapping function to
432      * each input element before accumulation.
433      *
434      * @apiNote
435      * The {@code mapping()} collectors are most useful when used in a
436      * multi-level reduction, such as downstream of a {@code groupingBy} or
437      * {@code partitioningBy}.  For example, given a stream of
438      * {@code Person}, to accumulate the set of last names in each city:
439      * <pre>{@code
440      * Map<City, Set<String>> lastNamesByCity
441      *   = people.stream().collect(
442      *     groupingBy(Person::getCity,
443      *                mapping(Person::getLastName,
444      *                        toSet())));
445      * }</pre>
446      *
447      * @param <T> the type of the input elements
448      * @param <U> type of elements accepted by downstream collector
449      * @param <A> intermediate accumulation type of the downstream collector
450      * @param <R> result type of collector
451      * @param mapper a function to be applied to the input elements
452      * @param downstream a collector which will accept mapped values
453      * @return a collector which applies the mapping function to the input
454      * elements and provides the mapped results to the downstream collector
455      */

456     public static <T, U, A, R>
457     Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
458                                Collector<? super U, A, R> downstream) {
459         BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
460         return new CollectorImpl<>(downstream.supplier(),
461                                    (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)),
462                                    downstream.combiner(), downstream.finisher(),
463                                    downstream.characteristics());
464     }
465
466     /**
467      * Adapts a {@code Collector} accepting elements of type {@code U} to one
468      * accepting elements of type {@code T} by applying a flat mapping function
469      * to each input element before accumulation.  The flat mapping function
470      * maps an input element to a {@link Stream stream} covering zero or more
471      * output elements that are then accumulated downstream.  Each mapped stream
472      * is {@link java.util.stream.BaseStream#close() closed} after its contents
473      * have been placed downstream.  (If a mapped stream is {@code null}
474      * an empty stream is used, instead.)
475      *
476      * @apiNote
477      * The {@code flatMapping()} collectors are most useful when used in a
478      * multi-level reduction, such as downstream of a {@code groupingBy} or
479      * {@code partitioningBy}.  For example, given a stream of
480      * {@code Order}, to accumulate the set of line items for each customer:
481      * <pre>{@code
482      * Map<String, Set<LineItem>> itemsByCustomerName
483      *   = orders.stream().collect(
484      *     groupingBy(Order::getCustomerName,
485      *                flatMapping(order -> order.getLineItems().stream(),
486      *                            toSet())));
487      * }</pre>
488      *
489      * @param <T> the type of the input elements
490      * @param <U> type of elements accepted by downstream collector
491      * @param <A> intermediate accumulation type of the downstream collector
492      * @param <R> result type of collector
493      * @param mapper a function to be applied to the input elements, which
494      * returns a stream of results
495      * @param downstream a collector which will receive the elements of the
496      * stream returned by mapper
497      * @return a collector which applies the mapping function to the input
498      * elements and provides the flat mapped results to the downstream collector
499      * @since 9
500      */

501     public static <T, U, A, R>
502     Collector<T, ?, R> flatMapping(Function<? super T, ? extends Stream<? extends U>> mapper,
503                                    Collector<? super U, A, R> downstream) {
504         BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator();
505         return new CollectorImpl<>(downstream.supplier(),
506                             (r, t) -> {
507                                 try (Stream<? extends U> result = mapper.apply(t)) {
508                                     if (result != null)
509                                         result.sequential().forEach(u -> downstreamAccumulator.accept(r, u));
510                                 }
511                             },
512                             downstream.combiner(), downstream.finisher(),
513                             downstream.characteristics());
514     }
515
516     /**
517      * Adapts a {@code Collector} to one accepting elements of the same type
518      * {@code T} by applying the predicate to each input element and only
519      * accumulating if the predicate returns {@code true}.
520      *
521      * @apiNote
522      * The {@code filtering()} collectors are most useful when used in a
523      * multi-level reduction, such as downstream of a {@code groupingBy} or
524      * {@code partitioningBy}.  For example, given a stream of
525      * {@code Employee}, to accumulate the employees in each department that have a
526      * salary above a certain threshold:
527      * <pre>{@code
528      * Map<Department, Set<Employee>> wellPaidEmployeesByDepartment
529      *   = employees.stream().collect(
530      *     groupingBy(Employee::getDepartment,
531      *                filtering(e -> e.getSalary() > 2000,
532      *                          toSet())));
533      * }</pre>
534      * A filtering collector differs from a stream's {@code filter()} operation.
535      * In this example, suppose there are no employees whose salary is above the
536      * threshold in some department.  Using a filtering collector as shown above
537      * would result in a mapping from that department to an empty {@code Set}.
538      * If a stream {@code filter()} operation were done instead, there would be
539      * no mapping for that department at all.
540      *
541      * @param <T> the type of the input elements
542      * @param <A> intermediate accumulation type of the downstream collector
543      * @param <R> result type of collector
544      * @param predicate a predicate to be applied to the input elements
545      * @param downstream a collector which will accept values that match the
546      * predicate
547      * @return a collector which applies the predicate to the input elements
548      * and provides matching elements to the downstream collector
549      * @since 9
550      */

551     public static <T, A, R>
552     Collector<T, ?, R> filtering(Predicate<? super T> predicate,
553                                  Collector<? super T, A, R> downstream) {
554         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
555         return new CollectorImpl<>(downstream.supplier(),
556                                    (r, t) -> {
557                                        if (predicate.test(t)) {
558                                            downstreamAccumulator.accept(r, t);
559                                        }
560                                    },
561                                    downstream.combiner(), downstream.finisher(),
562                                    downstream.characteristics());
563     }
564
565     /**
566      * Adapts a {@code Collector} to perform an additional finishing
567      * transformation.  For example, one could adapt the {@link #toList()}
568      * collector to always produce an immutable list with:
569      * <pre>{@code
570      * List<String> list = people.stream().collect(
571      *   collectingAndThen(toList(),
572      *                     Collections::unmodifiableList));
573      * }</pre>
574      *
575      * @param <T> the type of the input elements
576      * @param <A> intermediate accumulation type of the downstream collector
577      * @param <R> result type of the downstream collector
578      * @param <RR> result type of the resulting collector
579      * @param downstream a collector
580      * @param finisher a function to be applied to the final result of the downstream collector
581      * @return a collector which performs the action of the downstream collector,
582      * followed by an additional finishing step
583      */

584     public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
585                                                                 Function<R,RR> finisher) {
586         Set<Collector.Characteristics> characteristics = downstream.characteristics();
587         if (characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) {
588             if (characteristics.size() == 1)
589                 characteristics = Collectors.CH_NOID;
590             else {
591                 characteristics = EnumSet.copyOf(characteristics);
592                 characteristics.remove(Collector.Characteristics.IDENTITY_FINISH);
593                 characteristics = Collections.unmodifiableSet(characteristics);
594             }
595         }
596         return new CollectorImpl<>(downstream.supplier(),
597                                    downstream.accumulator(),
598                                    downstream.combiner(),
599                                    downstream.finisher().andThen(finisher),
600                                    characteristics);
601     }
602
603     /**
604      * Returns a {@code Collector} accepting elements of type {@code T} that
605      * counts the number of input elements.  If no elements are present, the
606      * result is 0.
607      *
608      * @implSpec
609      * This produces a result equivalent to:
610      * <pre>{@code
611      *     reducing(0L, e -> 1L, Long::sum)
612      * }</pre>
613      *
614      * @param <T> the type of the input elements
615      * @return a {@code Collector} that counts the input elements
616      */

617     public static <T> Collector<T, ?, Long>
618     counting() {
619         return summingLong(e -> 1L);
620     }
621
622     /**
623      * Returns a {@code Collector} that produces the minimal element according
624      * to a given {@code Comparator}, described as an {@code Optional<T>}.
625      *
626      * @implSpec
627      * This produces a result equivalent to:
628      * <pre>{@code
629      *     reducing(BinaryOperator.minBy(comparator))
630      * }</pre>
631      *
632      * @param <T> the type of the input elements
633      * @param comparator a {@code Comparator} for comparing elements
634      * @return a {@code Collector} that produces the minimal value
635      */

636     public static <T> Collector<T, ?, Optional<T>>
637     minBy(Comparator<? super T> comparator) {
638         return reducing(BinaryOperator.minBy(comparator));
639     }
640
641     /**
642      * Returns a {@code Collector} that produces the maximal element according
643      * to a given {@code Comparator}, described as an {@code Optional<T>}.
644      *
645      * @implSpec
646      * This produces a result equivalent to:
647      * <pre>{@code
648      *     reducing(BinaryOperator.maxBy(comparator))
649      * }</pre>
650      *
651      * @param <T> the type of the input elements
652      * @param comparator a {@code Comparator} for comparing elements
653      * @return a {@code Collector} that produces the maximal value
654      */

655     public static <T> Collector<T, ?, Optional<T>>
656     maxBy(Comparator<? super T> comparator) {
657         return reducing(BinaryOperator.maxBy(comparator));
658     }
659
660     /**
661      * Returns a {@code Collector} that produces the sum of a integer-valued
662      * function applied to the input elements.  If no elements are present,
663      * the result is 0.
664      *
665      * @param <T> the type of the input elements
666      * @param mapper a function extracting the property to be summed
667      * @return a {@code Collector} that produces the sum of a derived property
668      */

669     public static <T> Collector<T, ?, Integer>
670     summingInt(ToIntFunction<? super T> mapper) {
671         return new CollectorImpl<>(
672                 () -> new int[1],
673                 (a, t) -> { a[0] += mapper.applyAsInt(t); },
674                 (a, b) -> { a[0] += b[0]; return a; },
675                 a -> a[0], CH_NOID);
676     }
677
678     /**
679      * Returns a {@code Collector} that produces the sum of a long-valued
680      * function applied to the input elements.  If no elements are present,
681      * the result is 0.
682      *
683      * @param <T> the type of the input elements
684      * @param mapper a function extracting the property to be summed
685      * @return a {@code Collector} that produces the sum of a derived property
686      */

687     public static <T> Collector<T, ?, Long>
688     summingLong(ToLongFunction<? super T> mapper) {
689         return new CollectorImpl<>(
690                 () -> new long[1],
691                 (a, t) -> { a[0] += mapper.applyAsLong(t); },
692                 (a, b) -> { a[0] += b[0]; return a; },
693                 a -> a[0], CH_NOID);
694     }
695
696     /**
697      * Returns a {@code Collector} that produces the sum of a double-valued
698      * function applied to the input elements.  If no elements are present,
699      * the result is 0.
700      *
701      * <p>The sum returned can vary depending upon the order in which
702      * values are recorded, due to accumulated rounding error in
703      * addition of values of differing magnitudes. Values sorted by increasing
704      * absolute magnitude tend to yield more accurate results.  If any recorded
705      * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
706      * sum will be {@code NaN}.
707      *
708      * @param <T> the type of the input elements
709      * @param mapper a function extracting the property to be summed
710      * @return a {@code Collector} that produces the sum of a derived property
711      */

712     public static <T> Collector<T, ?, Double>
713     summingDouble(ToDoubleFunction<? super T> mapper) {
714         /*
715          * In the arrays allocated for the collect operation, index 0
716          * holds the high-order bits of the running sum, index 1 holds
717          * the low-order bits of the sum computed via compensated
718          * summation, and index 2 holds the simple sum used to compute
719          * the proper result if the stream contains infinite values of
720          * the same sign.
721          */

722         return new CollectorImpl<>(
723                 () -> new double[3],
724                 (a, t) -> { double val = mapper.applyAsDouble(t);
725                             sumWithCompensation(a, val);
726                             a[2] += val;},
727                 (a, b) -> { sumWithCompensation(a, b[0]);
728                             a[2] += b[2];
729                             return sumWithCompensation(a, b[1]); },
730                 a -> computeFinalSum(a),
731                 CH_NOID);
732     }
733
734     /**
735      * Incorporate a new double value using Kahan summation /
736      * compensation summation.
737      *
738      * High-order bits of the sum are in intermediateSum[0], low-order
739      * bits of the sum are in intermediateSum[1], any additional
740      * elements are application-specific.
741      *
742      * @param intermediateSum the high-order and low-order words of the intermediate sum
743      * @param value the name value to be included in the running sum
744      */

745     static double[] sumWithCompensation(double[] intermediateSum, double value) {
746         double tmp = value - intermediateSum[1];
747         double sum = intermediateSum[0];
748         double velvel = sum + tmp; // Little wolf of rounding error
749         intermediateSum[1] = (velvel - sum) - tmp;
750         intermediateSum[0] = velvel;
751         return intermediateSum;
752     }
753
754     /**
755      * If the compensated sum is spuriously NaN from accumulating one
756      * or more same-signed infinite values, return the
757      * correctly-signed infinity stored in the simple sum.
758      */

759     static double computeFinalSum(double[] summands) {
760         // Better error bounds to add both terms as the final sum
761         double tmp = summands[0] + summands[1];
762         double simpleSum = summands[summands.length - 1];
763         if (Double.isNaN(tmp) && Double.isInfinite(simpleSum))
764             return simpleSum;
765         else
766             return tmp;
767     }
768
769     /**
770      * Returns a {@code Collector} that produces the arithmetic mean of an integer-valued
771      * function applied to the input elements.  If no elements are present,
772      * the result is 0.
773      *
774      * @param <T> the type of the input elements
775      * @param mapper a function extracting the property to be averaged
776      * @return a {@code Collector} that produces the arithmetic mean of a
777      * derived property
778      */

779     public static <T> Collector<T, ?, Double>
780     averagingInt(ToIntFunction<? super T> mapper) {
781         return new CollectorImpl<>(
782                 () -> new long[2],
783                 (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; },
784                 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
785                 a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);
786     }
787
788     /**
789      * Returns a {@code Collector} that produces the arithmetic mean of a long-valued
790      * function applied to the input elements.  If no elements are present,
791      * the result is 0.
792      *
793      * @param <T> the type of the input elements
794      * @param mapper a function extracting the property to be averaged
795      * @return a {@code Collector} that produces the arithmetic mean of a
796      * derived property
797      */

798     public static <T> Collector<T, ?, Double>
799     averagingLong(ToLongFunction<? super T> mapper) {
800         return new CollectorImpl<>(
801                 () -> new long[2],
802                 (a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; },
803                 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
804                 a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);
805     }
806
807     /**
808      * Returns a {@code Collector} that produces the arithmetic mean of a double-valued
809      * function applied to the input elements.  If no elements are present,
810      * the result is 0.
811      *
812      * <p>The average returned can vary depending upon the order in which
813      * values are recorded, due to accumulated rounding error in
814      * addition of values of differing magnitudes. Values sorted by increasing
815      * absolute magnitude tend to yield more accurate results.  If any recorded
816      * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
817      * average will be {@code NaN}.
818      *
819      * @implNote The {@code double} format can represent all
820      * consecutive integers in the range -2<sup>53</sup> to
821      * 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup>
822      * values, the divisor in the average computation will saturate at
823      * 2<sup>53</sup>, leading to additional numerical errors.
824      *
825      * @param <T> the type of the input elements
826      * @param mapper a function extracting the property to be averaged
827      * @return a {@code Collector} that produces the arithmetic mean of a
828      * derived property
829      */

830     public static <T> Collector<T, ?, Double>
831     averagingDouble(ToDoubleFunction<? super T> mapper) {
832         /*
833          * In the arrays allocated for the collect operation, index 0
834          * holds the high-order bits of the running sum, index 1 holds
835          * the low-order bits of the sum computed via compensated
836          * summation, and index 2 holds the number of values seen.
837          */

838         return new CollectorImpl<>(
839                 () -> new double[4],
840                 (a, t) -> { double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2]++; a[3]+= val;},
841                 (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
842                 a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
843                 CH_NOID);
844     }
845
846     /**
847      * Returns a {@code Collector} which performs a reduction of its
848      * input elements under a specified {@code BinaryOperator} using the
849      * provided identity.
850      *
851      * @apiNote
852      * The {@code reducing()} collectors are most useful when used in a
853      * multi-level reduction, downstream of {@code groupingBy} or
854      * {@code partitioningBy}.  To perform a simple reduction on a stream,
855      * use {@link Stream#reduce(Object, BinaryOperator)}} instead.
856      *
857      * @param <T> element type for the input and output of the reduction
858      * @param identity the identity value for the reduction (also, the value
859      *                 that is returned when there are no input elements)
860      * @param op a {@code BinaryOperator<T>} used to reduce the input elements
861      * @return a {@code Collector} which implements the reduction operation
862      *
863      * @see #reducing(BinaryOperator)
864      * @see #reducing(Object, Function, BinaryOperator)
865      */

866     public static <T> Collector<T, ?, T>
867     reducing(T identity, BinaryOperator<T> op) {
868         return new CollectorImpl<>(
869                 boxSupplier(identity),
870                 (a, t) -> { a[0] = op.apply(a[0], t); },
871                 (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
872                 a -> a[0],
873                 CH_NOID);
874     }
875
876     @SuppressWarnings("unchecked")
877     private static <T> Supplier<T[]> boxSupplier(T identity) {
878         return () -> (T[]) new Object[] { identity };
879     }
880
881     /**
882      * Returns a {@code Collector} which performs a reduction of its
883      * input elements under a specified {@code BinaryOperator}.  The result
884      * is described as an {@code Optional<T>}.
885      *
886      * @apiNote
887      * The {@code reducing()} collectors are most useful when used in a
888      * multi-level reduction, downstream of {@code groupingBy} or
889      * {@code partitioningBy}.  To perform a simple reduction on a stream,
890      * use {@link Stream#reduce(BinaryOperator)} instead.
891      *
892      * <p>For example, given a stream of {@code Person}, to calculate tallest
893      * person in each city:
894      * <pre>{@code
895      * Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);
896      * Map<City, Optional<Person>> tallestByCity
897      *   = people.stream().collect(
898      *     groupingBy(Person::getCity,
899      *                reducing(BinaryOperator.maxBy(byHeight))));
900      * }</pre>
901      *
902      * @param <T> element type for the input and output of the reduction
903      * @param op a {@code BinaryOperator<T>} used to reduce the input elements
904      * @return a {@code Collector} which implements the reduction operation
905      *
906      * @see #reducing(Object, BinaryOperator)
907      * @see #reducing(Object, Function, BinaryOperator)
908      */

909     public static <T> Collector<T, ?, Optional<T>>
910     reducing(BinaryOperator<T> op) {
911         class OptionalBox implements Consumer<T> {
912             T value = null;
913             boolean present = false;
914
915             @Override
916             public void accept(T t) {
917                 if (present) {
918                     value = op.apply(value, t);
919                 }
920                 else {
921                     value = t;
922                     present = true;
923                 }
924             }
925         }
926
927         return new CollectorImpl<T, OptionalBox, Optional<T>>(
928                 OptionalBox::new, OptionalBox::accept,
929                 (a, b) -> { if (b.present) a.accept(b.value); return a; },
930                 a -> Optional.ofNullable(a.value), CH_NOID);
931     }
932
933     /**
934      * Returns a {@code Collector} which performs a reduction of its
935      * input elements under a specified mapping function and
936      * {@code BinaryOperator}. This is a generalization of
937      * {@link #reducing(Object, BinaryOperator)} which allows a transformation
938      * of the elements before reduction.
939      *
940      * @apiNote
941      * The {@code reducing()} collectors are most useful when used in a
942      * multi-level reduction, downstream of {@code groupingBy} or
943      * {@code partitioningBy}.  To perform a simple map-reduce on a stream,
944      * use {@link Stream#map(Function)} and {@link Stream#reduce(Object, BinaryOperator)}
945      * instead.
946      *
947      * <p>For example, given a stream of {@code Person}, to calculate the longest
948      * last name of residents in each city:
949      * <pre>{@code
950      * Comparator<String> byLength = Comparator.comparing(String::length);
951      * Map<City, String> longestLastNameByCity
952      *   = people.stream().collect(
953      *     groupingBy(Person::getCity,
954      *                reducing("",
955      *                         Person::getLastName,
956      *                         BinaryOperator.maxBy(byLength))));
957      * }</pre>
958      *
959      * @param <T> the type of the input elements
960      * @param <U> the type of the mapped values
961      * @param identity the identity value for the reduction (also, the value
962      *                 that is returned when there are no input elements)
963      * @param mapper a mapping function to apply to each input value
964      * @param op a {@code BinaryOperator<U>} used to reduce the mapped values
965      * @return a {@code Collector} implementing the map-reduce operation
966      *
967      * @see #reducing(Object, BinaryOperator)
968      * @see #reducing(BinaryOperator)
969      */

970     public static <T, U>
971     Collector<T, ?, U> reducing(U identity,
972                                 Function<? super T, ? extends U> mapper,
973                                 BinaryOperator<U> op) {
974         return new CollectorImpl<>(
975                 boxSupplier(identity),
976                 (a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); },
977                 (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
978                 a -> a[0], CH_NOID);
979     }
980
981     /**
982      * Returns a {@code Collector} implementing a "group by" operation on
983      * input elements of type {@code T}, grouping elements according to a
984      * classification function, and returning the results in a {@code Map}.
985      *
986      * <p>The classification function maps elements to some key type {@code K}.
987      * The collector produces a {@code Map<K, List<T>>} whose keys are the
988      * values resulting from applying the classification function to the input
989      * elements, and whose corresponding values are {@code List}s containing the
990      * input elements which map to the associated key under the classification
991      * function.
992      *
993      * <p>There are no guarantees on the type, mutability, serializability, or
994      * thread-safety of the {@code Map} or {@code List} objects returned.
995      * @implSpec
996      * This produces a result similar to:
997      * <pre>{@code
998      *     groupingBy(classifier, toList());
999      * }</pre>
1000      *
1001      * @implNote
1002      * The returned {@code Collector} is not concurrent.  For parallel stream
1003      * pipelines, the {@code combiner} function operates by merging the keys
1004      * from one map into another, which can be an expensive operation.  If
1005      * preservation of the order in which elements appear in the resulting {@code Map}
1006      * collector is not required, using {@link #groupingByConcurrent(Function)}
1007      * may offer better parallel performance.
1008      *
1009      * @param <T> the type of the input elements
1010      * @param <K> the type of the keys
1011      * @param classifier the classifier function mapping input elements to keys
1012      * @return a {@code Collector} implementing the group-by operation
1013      *
1014      * @see #groupingBy(Function, Collector)
1015      * @see #groupingBy(Function, Supplier, Collector)
1016      * @see #groupingByConcurrent(Function)
1017      */

1018     public static <T, K> Collector<T, ?, Map<K, List<T>>>
1019     groupingBy(Function<? super T, ? extends K> classifier) {
1020         return groupingBy(classifier, toList());
1021     }
1022
1023     /**
1024      * Returns a {@code Collector} implementing a cascaded "group by" operation
1025      * on input elements of type {@code T}, grouping elements according to a
1026      * classification function, and then performing a reduction operation on
1027      * the values associated with a given key using the specified downstream
1028      * {@code Collector}.
1029      *
1030      * <p>The classification function maps elements to some key type {@code K}.
1031      * The downstream collector operates on elements of type {@code T} and
1032      * produces a result of type {@code D}. The resulting collector produces a
1033      * {@code Map<K, D>}.
1034      *
1035      * <p>There are no guarantees on the type, mutability,
1036      * serializability, or thread-safety of the {@code Map} returned.
1037      *
1038      * <p>For example, to compute the set of last names of people in each city:
1039      * <pre>{@code
1040      * Map<City, Set<String>> namesByCity
1041      *   = people.stream().collect(
1042      *     groupingBy(Person::getCity,
1043      *                mapping(Person::getLastName,
1044      *                        toSet())));
1045      * }</pre>
1046      *
1047      * @implNote
1048      * The returned {@code Collector} is not concurrent.  For parallel stream
1049      * pipelines, the {@code combiner} function operates by merging the keys
1050      * from one map into another, which can be an expensive operation.  If
1051      * preservation of the order in which elements are presented to the downstream
1052      * collector is not required, using {@link #groupingByConcurrent(Function, Collector)}
1053      * may offer better parallel performance.
1054      *
1055      * @param <T> the type of the input elements
1056      * @param <K> the type of the keys
1057      * @param <A> the intermediate accumulation type of the downstream collector
1058      * @param <D> the result type of the downstream reduction
1059      * @param classifier a classifier function mapping input elements to keys
1060      * @param downstream a {@code Collector} implementing the downstream reduction
1061      * @return a {@code Collector} implementing the cascaded group-by operation
1062      * @see #groupingBy(Function)
1063      *
1064      * @see #groupingBy(Function, Supplier, Collector)
1065      * @see #groupingByConcurrent(Function, Collector)
1066      */

1067     public static <T, K, A, D>
1068     Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
1069                                           Collector<? super T, A, D> downstream) {
1070         return groupingBy(classifier, HashMap::new, downstream);
1071     }
1072
1073     /**
1074      * Returns a {@code Collector} implementing a cascaded "group by" operation
1075      * on input elements of type {@code T}, grouping elements according to a
1076      * classification function, and then performing a reduction operation on
1077      * the values associated with a given key using the specified downstream
1078      * {@code Collector}.  The {@code Map} produced by the Collector is created
1079      * with the supplied factory function.
1080      *
1081      * <p>The classification function maps elements to some key type {@code K}.
1082      * The downstream collector operates on elements of type {@code T} and
1083      * produces a result of type {@code D}. The resulting collector produces a
1084      * {@code Map<K, D>}.
1085      *
1086      * <p>For example, to compute the set of last names of people in each city,
1087      * where the city names are sorted:
1088      * <pre>{@code
1089      * Map<City, Set<String>> namesByCity
1090      *   = people.stream().collect(
1091      *     groupingBy(Person::getCity,
1092      *                TreeMap::new,
1093      *                mapping(Person::getLastName,
1094      *                        toSet())));
1095      * }</pre>
1096      *
1097      * @implNote
1098      * The returned {@code Collector} is not concurrent.  For parallel stream
1099      * pipelines, the {@code combiner} function operates by merging the keys
1100      * from one map into another, which can be an expensive operation.  If
1101      * preservation of the order in which elements are presented to the downstream
1102      * collector is not required, using {@link #groupingByConcurrent(Function, Supplier, Collector)}
1103      * may offer better parallel performance.
1104      *
1105      * @param <T> the type of the input elements
1106      * @param <K> the type of the keys
1107      * @param <A> the intermediate accumulation type of the downstream collector
1108      * @param <D> the result type of the downstream reduction
1109      * @param <M> the type of the resulting {@code Map}
1110      * @param classifier a classifier function mapping input elements to keys
1111      * @param downstream a {@code Collector} implementing the downstream reduction
1112      * @param mapFactory a supplier providing a new empty {@code Map}
1113      *                   into which the results will be inserted
1114      * @return a {@code Collector} implementing the cascaded group-by operation
1115      *
1116      * @see #groupingBy(Function, Collector)
1117      * @see #groupingBy(Function)
1118      * @see #groupingByConcurrent(Function, Supplier, Collector)
1119      */

1120     public static <T, K, D, A, M extends Map<K, D>>
1121     Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
1122                                   Supplier<M> mapFactory,
1123                                   Collector<? super T, A, D> downstream) {
1124         Supplier<A> downstreamSupplier = downstream.supplier();
1125         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
1126         BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
1127             K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
1128             A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
1129             downstreamAccumulator.accept(container, t);
1130         };
1131         BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner());
1132         @SuppressWarnings("unchecked")
1133         Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;
1134
1135         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
1136             return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
1137         }
1138         else {
1139             @SuppressWarnings("unchecked")
1140             Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
1141             Function<Map<K, A>, M> finisher = intermediate -> {
1142                 intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
1143                 @SuppressWarnings("unchecked")
1144                 M castResult = (M) intermediate;
1145                 return castResult;
1146             };
1147             return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
1148         }
1149     }
1150
1151     /**
1152      * Returns a concurrent {@code Collector} implementing a "group by"
1153      * operation on input elements of type {@code T}, grouping elements
1154      * according to a classification function.
1155      *
1156      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1157      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1158      *
1159      * <p>The classification function maps elements to some key type {@code K}.
1160      * The collector produces a {@code ConcurrentMap<K, List<T>>} whose keys are the
1161      * values resulting from applying the classification function to the input
1162      * elements, and whose corresponding values are {@code List}s containing the
1163      * input elements which map to the associated key under the classification
1164      * function.
1165      *
1166      * <p>There are no guarantees on the type, mutability, or serializability
1167      * of the {@code ConcurrentMap} or {@code List} objects returned, or of the
1168      * thread-safety of the {@code List} objects returned.
1169      * @implSpec
1170      * This produces a result similar to:
1171      * <pre>{@code
1172      *     groupingByConcurrent(classifier, toList());
1173      * }</pre>
1174      *
1175      * @param <T> the type of the input elements
1176      * @param <K> the type of the keys
1177      * @param classifier a classifier function mapping input elements to keys
1178      * @return a concurrent, unordered {@code Collector} implementing the group-by operation
1179      *
1180      * @see #groupingBy(Function)
1181      * @see #groupingByConcurrent(Function, Collector)
1182      * @see #groupingByConcurrent(Function, Supplier, Collector)
1183      */

1184     public static <T, K>
1185     Collector<T, ?, ConcurrentMap<K, List<T>>>
1186     groupingByConcurrent(Function<? super T, ? extends K> classifier) {
1187         return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
1188     }
1189
1190     /**
1191      * Returns a concurrent {@code Collector} implementing a cascaded "group by"
1192      * operation on input elements of type {@code T}, grouping elements
1193      * according to a classification function, and then performing a reduction
1194      * operation on the values associated with a given key using the specified
1195      * downstream {@code Collector}.
1196      *
1197      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1198      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1199      *
1200      * <p>The classification function maps elements to some key type {@code K}.
1201      * The downstream collector operates on elements of type {@code T} and
1202      * produces a result of type {@code D}. The resulting collector produces a
1203      * {@code ConcurrentMap<K, D>}.
1204      *
1205      * <p>There are no guarantees on the type, mutability, or serializability
1206      * of the {@code ConcurrentMap} returned.
1207      *
1208      * <p>For example, to compute the set of last names of people in each city,
1209      * where the city names are sorted:
1210      * <pre>{@code
1211      * ConcurrentMap<City, Set<String>> namesByCity
1212      *   = people.stream().collect(
1213      *     groupingByConcurrent(Person::getCity,
1214      *                          mapping(Person::getLastName,
1215      *                                  toSet())));
1216      * }</pre>
1217      *
1218      * @param <T> the type of the input elements
1219      * @param <K> the type of the keys
1220      * @param <A> the intermediate accumulation type of the downstream collector
1221      * @param <D> the result type of the downstream reduction
1222      * @param classifier a classifier function mapping input elements to keys
1223      * @param downstream a {@code Collector} implementing the downstream reduction
1224      * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
1225      *
1226      * @see #groupingBy(Function, Collector)
1227      * @see #groupingByConcurrent(Function)
1228      * @see #groupingByConcurrent(Function, Supplier, Collector)
1229      */

1230     public static <T, K, A, D>
1231     Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier,
1232                                                               Collector<? super T, A, D> downstream) {
1233         return groupingByConcurrent(classifier, ConcurrentHashMap::new, downstream);
1234     }
1235
1236     /**
1237      * Returns a concurrent {@code Collector} implementing a cascaded "group by"
1238      * operation on input elements of type {@code T}, grouping elements
1239      * according to a classification function, and then performing a reduction
1240      * operation on the values associated with a given key using the specified
1241      * downstream {@code Collector}.  The {@code ConcurrentMap} produced by the
1242      * Collector is created with the supplied factory function.
1243      *
1244      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1245      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1246      *
1247      * <p>The classification function maps elements to some key type {@code K}.
1248      * The downstream collector operates on elements of type {@code T} and
1249      * produces a result of type {@code D}. The resulting collector produces a
1250      * {@code ConcurrentMap<K, D>}.
1251      *
1252      * <p>For example, to compute the set of last names of people in each city,
1253      * where the city names are sorted:
1254      * <pre>{@code
1255      * ConcurrentMap<City, Set<String>> namesByCity
1256      *   = people.stream().collect(
1257      *     groupingByConcurrent(Person::getCity,
1258      *                          ConcurrentSkipListMap::new,
1259      *                          mapping(Person::getLastName,
1260      *                                  toSet())));
1261      * }</pre>
1262      *
1263      * @param <T> the type of the input elements
1264      * @param <K> the type of the keys
1265      * @param <A> the intermediate accumulation type of the downstream collector
1266      * @param <D> the result type of the downstream reduction
1267      * @param <M> the type of the resulting {@code ConcurrentMap}
1268      * @param classifier a classifier function mapping input elements to keys
1269      * @param downstream a {@code Collector} implementing the downstream reduction
1270      * @param mapFactory a supplier providing a new empty {@code ConcurrentMap}
1271      *                   into which the results will be inserted
1272      * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
1273      *
1274      * @see #groupingByConcurrent(Function)
1275      * @see #groupingByConcurrent(Function, Collector)
1276      * @see #groupingBy(Function, Supplier, Collector)
1277      */

1278     public static <T, K, A, D, M extends ConcurrentMap<K, D>>
1279     Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier,
1280                                             Supplier<M> mapFactory,
1281                                             Collector<? super T, A, D> downstream) {
1282         Supplier<A> downstreamSupplier = downstream.supplier();
1283         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
1284         BinaryOperator<ConcurrentMap<K, A>> merger = Collectors.<K, A, ConcurrentMap<K, A>>mapMerger(downstream.combiner());
1285         @SuppressWarnings("unchecked")
1286         Supplier<ConcurrentMap<K, A>> mangledFactory = (Supplier<ConcurrentMap<K, A>>) mapFactory;
1287         BiConsumer<ConcurrentMap<K, A>, T> accumulator;
1288         if (downstream.characteristics().contains(Collector.Characteristics.CONCURRENT)) {
1289             accumulator = (m, t) -> {
1290                 K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
1291                 A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
1292                 downstreamAccumulator.accept(resultContainer, t);
1293             };
1294         }
1295         else {
1296             accumulator = (m, t) -> {
1297                 K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
1298                 A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
1299                 synchronized (resultContainer) {
1300                     downstreamAccumulator.accept(resultContainer, t);
1301                 }
1302             };
1303         }
1304
1305         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
1306             return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_CONCURRENT_ID);
1307         }
1308         else {
1309             @SuppressWarnings("unchecked")
1310             Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
1311             Function<ConcurrentMap<K, A>, M> finisher = intermediate -> {
1312                 intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
1313                 @SuppressWarnings("unchecked")
1314                 M castResult = (M) intermediate;
1315                 return castResult;
1316             };
1317             return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID);
1318         }
1319     }
1320
1321     /**
1322      * Returns a {@code Collector} which partitions the input elements according
1323      * to a {@code Predicate}, and organizes them into a
1324      * {@code Map<Boolean, List<T>>}.
1325      *
1326      * The returned {@code Map} always contains mappings for both
1327      * {@code false} and {@code true} keys.
1328      * There are no guarantees on the type, mutability,
1329      * serializability, or thread-safety of the {@code Map} or {@code List}
1330      * returned.
1331      *
1332      * @apiNote
1333      * If a partition has no elements, its value in the result Map will be
1334      * an empty List.
1335      *
1336      * @param <T> the type of the input elements
1337      * @param predicate a predicate used for classifying input elements
1338      * @return a {@code Collector} implementing the partitioning operation
1339      *
1340      * @see #partitioningBy(Predicate, Collector)
1341      */

1342     public static <T>
1343     Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
1344         return partitioningBy(predicate, toList());
1345     }
1346
1347     /**
1348      * Returns a {@code Collector} which partitions the input elements according
1349      * to a {@code Predicate}, reduces the values in each partition according to
1350      * another {@code Collector}, and organizes them into a
1351      * {@code Map<Boolean, D>} whose values are the result of the downstream
1352      * reduction.
1353      *
1354      * <p>
1355      * The returned {@code Map} always contains mappings for both
1356      * {@code false} and {@code true} keys.
1357      * There are no guarantees on the type, mutability,
1358      * serializability, or thread-safety of the {@code Map} returned.
1359      *
1360      * @apiNote
1361      * If a partition has no elements, its value in the result Map will be
1362      * obtained by calling the downstream collector's supplier function and then
1363      * applying the finisher function.
1364      *
1365      * @param <T> the type of the input elements
1366      * @param <A> the intermediate accumulation type of the downstream collector
1367      * @param <D> the result type of the downstream reduction
1368      * @param predicate a predicate used for classifying input elements
1369      * @param downstream a {@code Collector} implementing the downstream
1370      *                   reduction
1371      * @return a {@code Collector} implementing the cascaded partitioning
1372      *         operation
1373      *
1374      * @see #partitioningBy(Predicate)
1375      */

1376     public static <T, D, A>
1377     Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
1378                                                     Collector<? super T, A, D> downstream) {
1379         BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
1380         BiConsumer<Partition<A>, T> accumulator = (result, t) ->
1381                 downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t);
1382         BinaryOperator<A> op = downstream.combiner();
1383         BinaryOperator<Partition<A>> merger = (left, right) ->
1384                 new Partition<>(op.apply(left.forTrue, right.forTrue),
1385                                 op.apply(left.forFalse, right.forFalse));
1386         Supplier<Partition<A>> supplier = () ->
1387                 new Partition<>(downstream.supplier().get(),
1388                                 downstream.supplier().get());
1389         if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
1390             return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
1391         }
1392         else {
1393             Function<Partition<A>, Map<Boolean, D>> finisher = par ->
1394                     new Partition<>(downstream.finisher().apply(par.forTrue),
1395                                     downstream.finisher().apply(par.forFalse));
1396             return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
1397         }
1398     }
1399
1400     /**
1401      * Returns a {@code Collector} that accumulates elements into a
1402      * {@code Map} whose keys and values are the result of applying the provided
1403      * mapping functions to the input elements.
1404      *
1405      * <p>If the mapped keys contain duplicates (according to
1406      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1407      * thrown when the collection operation is performed.  If the mapped keys
1408      * might have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
1409      * instead.
1410      *
1411      * <p>There are no guarantees on the type, mutability, serializability,
1412      * or thread-safety of the {@code Map} returned.
1413      *
1414      * @apiNote
1415      * It is common for either the key or the value to be the input elements.
1416      * In this case, the utility method
1417      * {@link java.util.function.Function#identity()} may be helpful.
1418      * For example, the following produces a {@code Map} mapping
1419      * students to their grade point average:
1420      * <pre>{@code
1421      * Map<Student, Double> studentToGPA
1422      *   = students.stream().collect(
1423      *     toMap(Function.identity(),
1424      *           student -> computeGPA(student)));
1425      * }</pre>
1426      * And the following produces a {@code Map} mapping a unique identifier to
1427      * students:
1428      * <pre>{@code
1429      * Map<String, Student> studentIdToStudent
1430      *   = students.stream().collect(
1431      *     toMap(Student::getId,
1432      *           Function.identity()));
1433      * }</pre>
1434      *
1435      * @implNote
1436      * The returned {@code Collector} is not concurrent.  For parallel stream
1437      * pipelines, the {@code combiner} function operates by merging the keys
1438      * from one map into another, which can be an expensive operation.  If it is
1439      * not required that results are inserted into the {@code Map} in encounter
1440      * order, using {@link #toConcurrentMap(Function, Function)}
1441      * may offer better parallel performance.
1442      *
1443      * @param <T> the type of the input elements
1444      * @param <K> the output type of the key mapping function
1445      * @param <U> the output type of the value mapping function
1446      * @param keyMapper a mapping function to produce keys
1447      * @param valueMapper a mapping function to produce values
1448      * @return a {@code Collector} which collects elements into a {@code Map}
1449      * whose keys and values are the result of applying mapping functions to
1450      * the input elements
1451      *
1452      * @see #toMap(Function, Function, BinaryOperator)
1453      * @see #toMap(Function, Function, BinaryOperator, Supplier)
1454      * @see #toConcurrentMap(Function, Function)
1455      */

1456     public static <T, K, U>
1457     Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
1458                                     Function<? super T, ? extends U> valueMapper) {
1459         return new CollectorImpl<>(HashMap::new,
1460                                    uniqKeysMapAccumulator(keyMapper, valueMapper),
1461                                    uniqKeysMapMerger(),
1462                                    CH_ID);
1463     }
1464
1465     /**
1466      * Returns a {@code Collector} that accumulates the input elements into an
1467      * <a href="../Map.html#unmodifiable">unmodifiable Map</a>,
1468      * whose keys and values are the result of applying the provided
1469      * mapping functions to the input elements.
1470      *
1471      * <p>If the mapped keys contain duplicates (according to
1472      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1473      * thrown when the collection operation is performed.  If the mapped keys
1474      * might have duplicates, use {@link #toUnmodifiableMap(Function, Function, BinaryOperator)}
1475      * to handle merging of the values.
1476      *
1477      * <p>The returned Collector disallows null keys and values. If either mapping function
1478      * returns null, {@code NullPointerException} will be thrown.
1479      *
1480      * @param <T> the type of the input elements
1481      * @param <K> the output type of the key mapping function
1482      * @param <U> the output type of the value mapping function
1483      * @param keyMapper a mapping function to produce keys, must be non-null
1484      * @param valueMapper a mapping function to produce values, must be non-null
1485      * @return a {@code Collector} that accumulates the input elements into an
1486      * <a href="../Map.html#unmodifiable">unmodifiable Map</a>, whose keys and values
1487      * are the result of applying the provided mapping functions to the input elements
1488      * @throws NullPointerException if either keyMapper or valueMapper is null
1489      *
1490      * @see #toUnmodifiableMap(Function, Function, BinaryOperator)
1491      * @since 10
1492      */

1493     @SuppressWarnings({"rawtypes""unchecked"})
1494     public static <T, K, U>
1495     Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
1496                                                 Function<? super T, ? extends U> valueMapper) {
1497         Objects.requireNonNull(keyMapper, "keyMapper");
1498         Objects.requireNonNull(valueMapper, "valueMapper");
1499         return collectingAndThen(
1500                 toMap(keyMapper, valueMapper),
1501                 map -> (Map<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
1502     }
1503
1504     /**
1505      * Returns a {@code Collector} that accumulates elements into a
1506      * {@code Map} whose keys and values are the result of applying the provided
1507      * mapping functions to the input elements.
1508      *
1509      * <p>If the mapped
1510      * keys contain duplicates (according to {@link Object#equals(Object)}),
1511      * the value mapping function is applied to each equal element, and the
1512      * results are merged using the provided merging function.
1513      *
1514      * <p>There are no guarantees on the type, mutability, serializability,
1515      * or thread-safety of the {@code Map} returned.
1516      *
1517      * @apiNote
1518      * There are multiple ways to deal with collisions between multiple elements
1519      * mapping to the same key.  The other forms of {@code toMap} simply use
1520      * a merge function that throws unconditionally, but you can easily write
1521      * more flexible merge policies.  For example, if you have a stream
1522      * of {@code Person}, and you want to produce a "phone book" mapping name to
1523      * address, but it is possible that two persons have the same name, you can
1524      * do as follows to gracefully deal with these collisions, and produce a
1525      * {@code Map} mapping names to a concatenated list of addresses:
1526      * <pre>{@code
1527      * Map<String, String> phoneBook
1528      *   = people.stream().collect(
1529      *     toMap(Person::getName,
1530      *           Person::getAddress,
1531      *           (s, a) -> s + ", " + a));
1532      * }</pre>
1533      *
1534      * @implNote
1535      * The returned {@code Collector} is not concurrent.  For parallel stream
1536      * pipelines, the {@code combiner} function operates by merging the keys
1537      * from one map into another, which can be an expensive operation.  If it is
1538      * not required that results are merged into the {@code Map} in encounter
1539      * order, using {@link #toConcurrentMap(Function, Function, BinaryOperator)}
1540      * may offer better parallel performance.
1541      *
1542      * @param <T> the type of the input elements
1543      * @param <K> the output type of the key mapping function
1544      * @param <U> the output type of the value mapping function
1545      * @param keyMapper a mapping function to produce keys
1546      * @param valueMapper a mapping function to produce values
1547      * @param mergeFunction a merge function, used to resolve collisions between
1548      *                      values associated with the same key, as supplied
1549      *                      to {@link Map#merge(Object, Object, BiFunction)}
1550      * @return a {@code Collector} which collects elements into a {@code Map}
1551      * whose keys are the result of applying a key mapping function to the input
1552      * elements, and whose values are the result of applying a value mapping
1553      * function to all input elements equal to the key and combining them
1554      * using the merge function
1555      *
1556      * @see #toMap(Function, Function)
1557      * @see #toMap(Function, Function, BinaryOperator, Supplier)
1558      * @see #toConcurrentMap(Function, Function, BinaryOperator)
1559      */

1560     public static <T, K, U>
1561     Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
1562                                     Function<? super T, ? extends U> valueMapper,
1563                                     BinaryOperator<U> mergeFunction) {
1564         return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
1565     }
1566
1567
1568     /**
1569      * Returns a {@code Collector} that accumulates the input elements into an
1570      * <a href="../Map.html#unmodifiable">unmodifiable Map</a>,
1571      * whose keys and values are the result of applying the provided
1572      * mapping functions to the input elements.
1573      *
1574      * <p>If the mapped
1575      * keys contain duplicates (according to {@link Object#equals(Object)}),
1576      * the value mapping function is applied to each equal element, and the
1577      * results are merged using the provided merging function.
1578      *
1579      * <p>The returned Collector disallows null keys and values. If either mapping function
1580      * returns null, {@code NullPointerException} will be thrown.
1581      *
1582      * @param <T> the type of the input elements
1583      * @param <K> the output type of the key mapping function
1584      * @param <U> the output type of the value mapping function
1585      * @param keyMapper a mapping function to produce keys, must be non-null
1586      * @param valueMapper a mapping function to produce values, must be non-null
1587      * @param mergeFunction a merge function, used to resolve collisions between
1588      *                      values associated with the same key, as supplied
1589      *                      to {@link Map#merge(Object, Object, BiFunction)},
1590      *                      must be non-null
1591      * @return a {@code Collector} that accumulates the input elements into an
1592      * <a href="../Map.html#unmodifiable">unmodifiable Map</a>, whose keys and values
1593      * are the result of applying the provided mapping functions to the input elements
1594      * @throws NullPointerException if the keyMapper, valueMapper, or mergeFunction is null
1595      *
1596      * @see #toUnmodifiableMap(Function, Function)
1597      * @since 10
1598      */

1599     @SuppressWarnings({"rawtypes""unchecked"})
1600     public static <T, K, U>
1601     Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
1602                                                 Function<? super T, ? extends U> valueMapper,
1603                                                 BinaryOperator<U> mergeFunction) {
1604         Objects.requireNonNull(keyMapper, "keyMapper");
1605         Objects.requireNonNull(valueMapper, "valueMapper");
1606         Objects.requireNonNull(mergeFunction, "mergeFunction");
1607         return collectingAndThen(
1608                 toMap(keyMapper, valueMapper, mergeFunction, HashMap::new),
1609                 map -> (Map<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
1610     }
1611
1612     /**
1613      * Returns a {@code Collector} that accumulates elements into a
1614      * {@code Map} whose keys and values are the result of applying the provided
1615      * mapping functions to the input elements.
1616      *
1617      * <p>If the mapped
1618      * keys contain duplicates (according to {@link Object#equals(Object)}),
1619      * the value mapping function is applied to each equal element, and the
1620      * results are merged using the provided merging function.  The {@code Map}
1621      * is created by a provided supplier function.
1622      *
1623      * @implNote
1624      * The returned {@code Collector} is not concurrent.  For parallel stream
1625      * pipelines, the {@code combiner} function operates by merging the keys
1626      * from one map into another, which can be an expensive operation.  If it is
1627      * not required that results are merged into the {@code Map} in encounter
1628      * order, using {@link #toConcurrentMap(Function, Function, BinaryOperator, Supplier)}
1629      * may offer better parallel performance.
1630      *
1631      * @param <T> the type of the input elements
1632      * @param <K> the output type of the key mapping function
1633      * @param <U> the output type of the value mapping function
1634      * @param <M> the type of the resulting {@code Map}
1635      * @param keyMapper a mapping function to produce keys
1636      * @param valueMapper a mapping function to produce values
1637      * @param mergeFunction a merge function, used to resolve collisions between
1638      *                      values associated with the same key, as supplied
1639      *                      to {@link Map#merge(Object, Object, BiFunction)}
1640      * @param mapFactory a supplier providing a new empty {@code Map}
1641      *                   into which the results will be inserted
1642      * @return a {@code Collector} which collects elements into a {@code Map}
1643      * whose keys are the result of applying a key mapping function to the input
1644      * elements, and whose values are the result of applying a value mapping
1645      * function to all input elements equal to the key and combining them
1646      * using the merge function
1647      *
1648      * @see #toMap(Function, Function)
1649      * @see #toMap(Function, Function, BinaryOperator)
1650      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
1651      */

1652     public static <T, K, U, M extends Map<K, U>>
1653     Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
1654                              Function<? super T, ? extends U> valueMapper,
1655                              BinaryOperator<U> mergeFunction,
1656                              Supplier<M> mapFactory) {
1657         BiConsumer<M, T> accumulator
1658                 = (map, element) -> map.merge(keyMapper.apply(element),
1659                                               valueMapper.apply(element), mergeFunction);
1660         return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_ID);
1661     }
1662
1663     /**
1664      * Returns a concurrent {@code Collector} that accumulates elements into a
1665      * {@code ConcurrentMap} whose keys and values are the result of applying
1666      * the provided mapping functions to the input elements.
1667      *
1668      * <p>If the mapped keys contain duplicates (according to
1669      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1670      * thrown when the collection operation is performed.  If the mapped keys
1671      * may have duplicates, use
1672      * {@link #toConcurrentMap(Function, Function, BinaryOperator)} instead.
1673      *
1674      * <p>There are no guarantees on the type, mutability, or serializability
1675      * of the {@code ConcurrentMap} returned.
1676      *
1677      * @apiNote
1678      * It is common for either the key or the value to be the input elements.
1679      * In this case, the utility method
1680      * {@link java.util.function.Function#identity()} may be helpful.
1681      * For example, the following produces a {@code ConcurrentMap} mapping
1682      * students to their grade point average:
1683      * <pre>{@code
1684      * ConcurrentMap<Student, Double> studentToGPA
1685      *   = students.stream().collect(
1686      *     toConcurrentMap(Function.identity(),
1687      *                     student -> computeGPA(student)));
1688      * }</pre>
1689      * And the following produces a {@code ConcurrentMap} mapping a
1690      * unique identifier to students:
1691      * <pre>{@code
1692      * ConcurrentMap<String, Student> studentIdToStudent
1693      *   = students.stream().collect(
1694      *     toConcurrentMap(Student::getId,
1695      *                     Function.identity()));
1696      * }</pre>
1697      *
1698      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1699      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1700      *
1701      * @param <T> the type of the input elements
1702      * @param <K> the output type of the key mapping function
1703      * @param <U> the output type of the value mapping function
1704      * @param keyMapper the mapping function to produce keys
1705      * @param valueMapper the mapping function to produce values
1706      * @return a concurrent, unordered {@code Collector} which collects elements into a
1707      * {@code ConcurrentMap} whose keys are the result of applying a key mapping
1708      * function to the input elements, and whose values are the result of
1709      * applying a value mapping function to the input elements
1710      *
1711      * @see #toMap(Function, Function)
1712      * @see #toConcurrentMap(Function, Function, BinaryOperator)
1713      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
1714      */

1715     public static <T, K, U>
1716     Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
1717                                                         Function<? super T, ? extends U> valueMapper) {
1718         return new CollectorImpl<>(ConcurrentHashMap::new,
1719                                    uniqKeysMapAccumulator(keyMapper, valueMapper),
1720                                    uniqKeysMapMerger(),
1721                                    CH_CONCURRENT_ID);
1722     }
1723
1724     /**
1725      * Returns a concurrent {@code Collector} that accumulates elements into a
1726      * {@code ConcurrentMap} whose keys and values are the result of applying
1727      * the provided mapping functions to the input elements.
1728      *
1729      * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}),
1730      * the value mapping function is applied to each equal element, and the
1731      * results are merged using the provided merging function.
1732      *
1733      * <p>There are no guarantees on the type, mutability, or serializability
1734      * of the {@code ConcurrentMap} returned.
1735      *
1736      * @apiNote
1737      * There are multiple ways to deal with collisions between multiple elements
1738      * mapping to the same key.  The other forms of {@code toConcurrentMap} simply use
1739      * a merge function that throws unconditionally, but you can easily write
1740      * more flexible merge policies.  For example, if you have a stream
1741      * of {@code Person}, and you want to produce a "phone book" mapping name to
1742      * address, but it is possible that two persons have the same name, you can
1743      * do as follows to gracefully deal with these collisions, and produce a
1744      * {@code ConcurrentMap} mapping names to a concatenated list of addresses:
1745      * <pre>{@code
1746      * ConcurrentMap<String, String> phoneBook
1747      *   = people.stream().collect(
1748      *     toConcurrentMap(Person::getName,
1749      *                     Person::getAddress,
1750      *                     (s, a) -> s + ", " + a));
1751      * }</pre>
1752      *
1753      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1754      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1755      *
1756      * @param <T> the type of the input elements
1757      * @param <K> the output type of the key mapping function
1758      * @param <U> the output type of the value mapping function
1759      * @param keyMapper a mapping function to produce keys
1760      * @param valueMapper a mapping function to produce values
1761      * @param mergeFunction a merge function, used to resolve collisions between
1762      *                      values associated with the same key, as supplied
1763      *                      to {@link Map#merge(Object, Object, BiFunction)}
1764      * @return a concurrent, unordered {@code Collector} which collects elements into a
1765      * {@code ConcurrentMap} whose keys are the result of applying a key mapping
1766      * function to the input elements, and whose values are the result of
1767      * applying a value mapping function to all input elements equal to the key
1768      * and combining them using the merge function
1769      *
1770      * @see #toConcurrentMap(Function, Function)
1771      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
1772      * @see #toMap(Function, Function, BinaryOperator)
1773      */

1774     public static <T, K, U>
1775     Collector<T, ?, ConcurrentMap<K,U>>
1776     toConcurrentMap(Function<? super T, ? extends K> keyMapper,
1777                     Function<? super T, ? extends U> valueMapper,
1778                     BinaryOperator<U> mergeFunction) {
1779         return toConcurrentMap(keyMapper, valueMapper, mergeFunction, ConcurrentHashMap::new);
1780     }
1781
1782     /**
1783      * Returns a concurrent {@code Collector} that accumulates elements into a
1784      * {@code ConcurrentMap} whose keys and values are the result of applying
1785      * the provided mapping functions to the input elements.
1786      *
1787      * <p>If the mapped keys contain duplicates (according to {@link Object#equals(Object)}),
1788      * the value mapping function is applied to each equal element, and the
1789      * results are merged using the provided merging function.  The
1790      * {@code ConcurrentMap} is created by a provided supplier function.
1791      *
1792      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1793      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1794      *
1795      * @param <T> the type of the input elements
1796      * @param <K> the output type of the key mapping function
1797      * @param <U> the output type of the value mapping function
1798      * @param <M> the type of the resulting {@code ConcurrentMap}
1799      * @param keyMapper a mapping function to produce keys
1800      * @param valueMapper a mapping function to produce values
1801      * @param mergeFunction a merge function, used to resolve collisions between
1802      *                      values associated with the same key, as supplied
1803      *                      to {@link Map#merge(Object, Object, BiFunction)}
1804      * @param mapFactory a supplier providing a new empty {@code ConcurrentMap}
1805      *                   into which the results will be inserted
1806      * @return a concurrent, unordered {@code Collector} which collects elements into a
1807      * {@code ConcurrentMap} whose keys are the result of applying a key mapping
1808      * function to the input elements, and whose values are the result of
1809      * applying a value mapping function to all input elements equal to the key
1810      * and combining them using the merge function
1811      *
1812      * @see #toConcurrentMap(Function, Function)
1813      * @see #toConcurrentMap(Function, Function, BinaryOperator)
1814      * @see #toMap(Function, Function, BinaryOperator, Supplier)
1815      */

1816     public static <T, K, U, M extends ConcurrentMap<K, U>>
1817     Collector<T, ?, M> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
1818                                        Function<? super T, ? extends U> valueMapper,
1819                                        BinaryOperator<U> mergeFunction,
1820                                        Supplier<M> mapFactory) {
1821         BiConsumer<M, T> accumulator
1822                 = (map, element) -> map.merge(keyMapper.apply(element),
1823                                               valueMapper.apply(element), mergeFunction);
1824         return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_CONCURRENT_ID);
1825     }
1826
1827     /**
1828      * Returns a {@code Collector} which applies an {@code int}-producing
1829      * mapping function to each input element, and returns summary statistics
1830      * for the resulting values.
1831      *
1832      * @param <T> the type of the input elements
1833      * @param mapper a mapping function to apply to each element
1834      * @return a {@code Collector} implementing the summary-statistics reduction
1835      *
1836      * @see #summarizingDouble(ToDoubleFunction)
1837      * @see #summarizingLong(ToLongFunction)
1838      */

1839     public static <T>
1840     Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) {
1841         return new CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>(
1842                 IntSummaryStatistics::new,
1843                 (r, t) -> r.accept(mapper.applyAsInt(t)),
1844                 (l, r) -> { l.combine(r); return l; }, CH_ID);
1845     }
1846
1847     /**
1848      * Returns a {@code Collector} which applies an {@code long}-producing
1849      * mapping function to each input element, and returns summary statistics
1850      * for the resulting values.
1851      *
1852      * @param <T> the type of the input elements
1853      * @param mapper the mapping function to apply to each element
1854      * @return a {@code Collector} implementing the summary-statistics reduction
1855      *
1856      * @see #summarizingDouble(ToDoubleFunction)
1857      * @see #summarizingInt(ToIntFunction)
1858      */

1859     public static <T>
1860     Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) {
1861         return new CollectorImpl<T, LongSummaryStatistics, LongSummaryStatistics>(
1862                 LongSummaryStatistics::new,
1863                 (r, t) -> r.accept(mapper.applyAsLong(t)),
1864                 (l, r) -> { l.combine(r); return l; }, CH_ID);
1865     }
1866
1867     /**
1868      * Returns a {@code Collector} which applies an {@code double}-producing
1869      * mapping function to each input element, and returns summary statistics
1870      * for the resulting values.
1871      *
1872      * @param <T> the type of the input elements
1873      * @param mapper a mapping function to apply to each element
1874      * @return a {@code Collector} implementing the summary-statistics reduction
1875      *
1876      * @see #summarizingLong(ToLongFunction)
1877      * @see #summarizingInt(ToIntFunction)
1878      */

1879     public static <T>
1880     Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) {
1881         return new CollectorImpl<T, DoubleSummaryStatistics, DoubleSummaryStatistics>(
1882                 DoubleSummaryStatistics::new,
1883                 (r, t) -> r.accept(mapper.applyAsDouble(t)),
1884                 (l, r) -> { l.combine(r); return l; }, CH_ID);
1885     }
1886
1887     /**
1888      * Implementation class used by partitioningBy.
1889      */

1890     private static final class Partition<T>
1891             extends AbstractMap<Boolean, T>
1892             implements Map<Boolean, T> {
1893         final T forTrue;
1894         final T forFalse;
1895
1896         Partition(T forTrue, T forFalse) {
1897             this.forTrue = forTrue;
1898             this.forFalse = forFalse;
1899         }
1900
1901         @Override
1902         public Set<Map.Entry<Boolean, T>> entrySet() {
1903             return new AbstractSet<>() {
1904                 @Override
1905                 public Iterator<Map.Entry<Boolean, T>> iterator() {
1906                     Map.Entry<Boolean, T> falseEntry = new SimpleImmutableEntry<>(false, forFalse);
1907                     Map.Entry<Boolean, T> trueEntry = new SimpleImmutableEntry<>(true, forTrue);
1908                     return List.of(falseEntry, trueEntry).iterator();
1909                 }
1910
1911                 @Override
1912                 public int size() {
1913                     return 2;
1914                 }
1915             };
1916         }
1917     }
1918 }
1919