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 != null) throw 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 != null) throw 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