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