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