1 /* 2 * Copyright (c) 2012, 2013, 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.Arrays; 31 import java.util.Collection; 32 import java.util.Collections; 33 import java.util.Comparator; 34 import java.util.DoubleSummaryStatistics; 35 import java.util.EnumSet; 36 import java.util.HashMap; 37 import java.util.HashSet; 38 import java.util.IntSummaryStatistics; 39 import java.util.Iterator; 40 import java.util.List; 41 import java.util.LongSummaryStatistics; 42 import java.util.Map; 43 import java.util.Objects; 44 import java.util.Optional; 45 import java.util.Set; 46 import java.util.StringJoiner; 47 import java.util.concurrent.ConcurrentHashMap; 48 import java.util.concurrent.ConcurrentMap; 49 import java.util.function.BiConsumer; 50 import java.util.function.BiFunction; 51 import java.util.function.BinaryOperator; 52 import java.util.function.Consumer; 53 import java.util.function.Function; 54 import java.util.function.Predicate; 55 import java.util.function.Supplier; 56 import java.util.function.ToDoubleFunction; 57 import java.util.function.ToIntFunction; 58 import java.util.function.ToLongFunction; 59 60 /** 61 * Implementations of {@link Collector} that implement various useful reduction 62 * operations, such as accumulating elements into collections, summarizing 63 * elements according to various criteria, etc. 64 * 65 * <p>The following are examples of using the predefined {@code Collector} 66 * implementations in {@link Collectors} with the {@code Stream} API to perform 67 * mutable reduction tasks: 68 * 69 * <pre>{@code 70 * // Accumulate names into a List 71 * List<String> list = people.stream().map(Person::getName).collect(Collectors.toList()); 72 * 73 * // Accumulate names into a TreeSet 74 * Set<String> list = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new)); 75 * 76 * // Convert elements to strings and concatenate them, separated by commas 77 * String joined = things.stream() 78 * .map(Object::toString) 79 * .collect(Collectors.joining(", ")); 80 * 81 * // Find highest-paid employee 82 * Employee highestPaid = employees.stream() 83 * .collect(Collectors.maxBy(Comparator.comparing(Employee::getSalary))) 84 * .get(); 85 * 86 * // Group employees by department 87 * Map<Department, List<Employee>> byDept 88 * = employees.stream() 89 * .collect(Collectors.groupingBy(Employee::getDepartment)); 90 * 91 * // Find highest-paid employee by department 92 * Map<Department, Optional<Employee>> highestPaidByDept 93 * = employees.stream() 94 * .collect(Collectors.groupingBy(Employee::getDepartment, 95 * Collectors.maxBy(Comparator.comparing(Employee::getSalary)))); 96 * 97 * // Partition students into passing and failing 98 * Map<Boolean, List<Student>> passingFailing = 99 * students.stream() 100 * .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD)); 101 * 102 * }</pre> 103 * 104 * TODO explanation of parallel collection 105 * 106 * @since 1.8 107 */ 108 public final class Collectors { 109 110 static final Set<Collector.Characteristics> CH_CONCURRENT_ID 111 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT, 112 Collector.Characteristics.UNORDERED, 113 Collector.Characteristics.IDENTITY_FINISH)); 114 static final Set<Collector.Characteristics> CH_CONCURRENT_NOID 115 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT, 116 Collector.Characteristics.UNORDERED)); 117 static final Set<Collector.Characteristics> CH_ID 118 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH)); 119 static final Set<Collector.Characteristics> CH_UNORDERED_ID 120 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED, 121 Collector.Characteristics.IDENTITY_FINISH)); 122 static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet(); 123 124 private Collectors() { } 125 126 /** 127 * Returns a merge function, suitable for use in 128 * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or 129 * {@link #toMap(Function, Function, BinaryOperator) toMap()}, which always 130 * throws {@code IllegalStateException}. This can be used to enforce the 131 * assumption that the elements being collected are distinct. 132 * 133 * @param <T> the type of input arguments to the merge function 134 * @return a merge function which always throw {@code IllegalStateException} 135 */ 136 private static <T> BinaryOperator<T> throwingMerger() { 137 return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); }; 138 } 139 140 /** 141 * Simple implementation class for {@code Collector}. 142 * 143 * @param <T> the type of elements to be collected 144 * @param <R> the type of the result 145 */ 146 static class CollectorImpl<T, A, R> implements Collector<T, A, R> { 147 private final Supplier<A> supplier; 148 private final BiConsumer<A, T> accumulator; 149 private final BinaryOperator<A> combiner; 150 private final Function<A, R> finisher; 151 private final Set<Characteristics> characteristics; 152 153 CollectorImpl(Supplier<A> supplier, 154 BiConsumer<A, T> accumulator, 155 BinaryOperator<A> combiner, 156 Function<A,R> finisher, 157 Set<Characteristics> characteristics) { 158 this.supplier = supplier; 159 this.accumulator = accumulator; 160 this.combiner = combiner; 161 this.finisher = finisher; 162 this.characteristics = characteristics; 163 } 164 165 CollectorImpl(Supplier<A> supplier, 166 BiConsumer<A, T> accumulator, 167 BinaryOperator<A> combiner, 168 Set<Characteristics> characteristics) { 169 this(supplier, accumulator, combiner, i -> (R) i, characteristics); 170 } 171 172 @Override 173 public BiConsumer<A, T> accumulator() { 174 return accumulator; 175 } 176 177 @Override 178 public Supplier<A> supplier() { 179 return supplier; 180 } 181 182 @Override 183 public BinaryOperator<A> combiner() { 184 return combiner; 185 } 186 187 @Override 188 public Function<A, R> finisher() { 189 return finisher; 190 } 191 192 @Override 193 public Set<Characteristics> characteristics() { 194 return characteristics; 195 } 196 } 197 198 /** 199 * Returns a {@code Collector} that accumulates the input elements into a 200 * new {@code Collection}, in encounter order. The {@code Collection} is 201 * created by the provided factory. 202 * 203 * @param <T> the type of the input elements 204 * @param <C> the type of the resulting {@code Collection} 205 * @param collectionFactory a {@code Supplier} which returns a new, empty 206 * {@code Collection} of the appropriate type 207 * @return a {@code Collector} which collects all the input elements into a 208 * {@code Collection}, in encounter order 209 */ 210 public static <T, C extends Collection<T>> 211 Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) { 212 return new CollectorImpl<>(collectionFactory, Collection::add, 213 (r1, r2) -> { r1.addAll(r2); return r1; }, 214 CH_ID); 215 } 216 217 /** 218 * Returns a {@code Collector} that accumulates the input elements into a 219 * new {@code List}. There are no guarantees on the type, mutability, 220 * serializability, or thread-safety of the {@code List} returned. 221 * 222 * @param <T> the type of the input elements 223 * @return a {@code Collector} which collects all the input elements into a 224 * {@code List}, in encounter order 225 */ 226 public static <T> 227 Collector<T, ?, List<T>> toList() { 228 return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add, 229 (left, right) -> { left.addAll(right); return left; }, 230 CH_ID); 231 } 232 233 /** 234 * Returns a {@code Collector} that accumulates the input elements into a 235 * new {@code Set}. There are no guarantees on the type, mutability, 236 * serializability, or thread-safety of the {@code Set} returned. 237 * 238 * <p>This is an {@link Collector.Characteristics#UNORDERED unordered} 239 * Collector. 240 * 241 * @param <T> the type of the input elements 242 * @return a {@code Collector} which collects all the input elements into a 243 * {@code Set} 244 */ 245 public static <T> 246 Collector<T, ?, Set<T>> toSet() { 247 return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add, 248 (left, right) -> { left.addAll(right); return left; }, 249 CH_UNORDERED_ID); 250 } 251 252 /** 253 * Returns a {@code Collector} that concatenates the input elements into a 254 * {@code String}, in encounter order. 255 * 256 * @return a {@code Collector} that concatenates the input elements into a 257 * {@code String}, in encounter order 258 */ 259 public static Collector<CharSequence, ?, String> joining() { 260 return new CollectorImpl<CharSequence, StringBuilder, String>( 261 StringBuilder::new, StringBuilder::append, 262 (r1, r2) -> { r1.append(r2); return r1; }, 263 StringBuilder::toString, CH_NOID); 264 } 265 266 /** 267 * Returns a {@code Collector} that concatenates the input elements, 268 * separated by the specified delimiter, in encounter order. 269 * 270 * @param delimiter the delimiter to be used between each element 271 * @return A {@code Collector} which concatenates CharSequence elements, 272 * separated by the specified delimiter, in encounter order 273 */ 274 public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) { 275 return joining(delimiter, "", ""); 276 } 277 278 /** 279 * Returns a {@code Collector} that concatenates the input elements, 280 * separated by the specified delimiter, with the specified prefix and 281 * suffix, in encounter order. 282 * 283 * @param delimiter the delimiter to be used between each element 284 * @param prefix the sequence of characters to be used at the beginning 285 * of the joined result 286 * @param suffix the sequence of characters to be used at the end 287 * of the joined result 288 * @return A {@code Collector} which concatenates CharSequence elements, 289 * separated by the specified delimiter, in encounter order 290 */ 291 public static Collector<CharSequence, ?, String> joining(CharSequence delimiter, 292 CharSequence prefix, 293 CharSequence suffix) { 294 return new CollectorImpl<>( 295 () -> new StringJoiner(delimiter, prefix, suffix), 296 StringJoiner::add, StringJoiner::merge, 297 StringJoiner::toString, CH_NOID); 298 } 299 300 /** 301 * {@code BinaryOperator<Map>} that merges the contents of its right 302 * argument into its left argument, using the provided merge function to 303 * handle duplicate keys. 304 * 305 * @param <K> type of the map keys 306 * @param <V> type of the map values 307 * @param <M> type of the map 308 * @param mergeFunction A merge function suitable for 309 * {@link Map#merge(Object, Object, BiFunction) Map.merge()} 310 * @return a merge function for two maps 311 */ 312 private static <K, V, M extends Map<K,V>> 313 BinaryOperator<M> mapMerger(BinaryOperator<V> mergeFunction) { 314 return (m1, m2) -> { 315 for (Map.Entry<K,V> e : m2.entrySet()) 316 m1.merge(e.getKey(), e.getValue(), mergeFunction); 317 return m1; 318 }; 319 } 320 321 /** 322 * Adapts a {@code Collector} accepting elements of type {@code U} to one 323 * accepting elements of type {@code T} by applying a mapping function to 324 * each input element before accumulation. 325 * 326 * @apiNote 327 * The {@code mapping()} collectors are most useful when used in a 328 * multi-level reduction, such as downstream of a {@code groupingBy} or 329 * {@code partitioningBy}. For example, given a stream of 330 * {@code Person}, to accumulate the set of last names in each city: 331 * <pre>{@code 332 * Map<City, Set<String>> lastNamesByCity 333 * = people.stream().collect(groupingBy(Person::getCity, 334 * mapping(Person::getLastName, toSet()))); 335 * }</pre> 336 * 337 * @param <T> the type of the input elements 338 * @param <U> type of elements accepted by downstream collector 339 * @param <A> intermediate accumulation type of the downstream collector 340 * @param <R> result type of collector 341 * @param mapper a function to be applied to the input elements 342 * @param downstream a collector which will accept mapped values 343 * @return a collector which applies the mapping function to the input 344 * elements and provides the mapped results to the downstream collector 345 */ 346 public static <T, U, A, R> 347 Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper, 348 Collector<? super U, A, R> downstream) { 349 BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator(); 350 return new CollectorImpl<>(downstream.supplier(), 351 (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)), 352 downstream.combiner(), downstream.finisher(), 353 downstream.characteristics()); 354 } 355 356 /** 357 * Returns a {@code Collector} accepting elements of type {@code T} that 358 * counts the number of input elements. If no elements are present, the 359 * result is 0. 360 * 361 * @implSpec 362 * This produces a result equivalent to: 363 * <pre>{@code 364 * reducing(0L, e -> 1L, Long::sum) 365 * }</pre> 366 * 367 * @param <T> the type of the input elements 368 * @return a {@code Collector} that counts the input elements 369 */ 370 public static <T> Collector<T, ?, Long> 371 counting() { 372 return reducing(0L, e -> 1L, Long::sum); 373 } 374 375 /** 376 * Returns a {@code Collector} that produces the minimal element according 377 * to a given {@code Comparator}, described as an {@code Optional<T>}. 378 * 379 * @implSpec 380 * This produces a result equivalent to: 381 * <pre>{@code 382 * reducing(BinaryOperator.minBy(comparator)) 383 * }</pre> 384 * 385 * @param <T> the type of the input elements 386 * @param comparator a {@code Comparator} for comparing elements 387 * @return a {@code Collector} that produces the minimal value 388 */ 389 public static <T> Collector<T, ?, Optional<T>> 390 minBy(Comparator<? super T> comparator) { 391 return reducing(BinaryOperator.minBy(comparator)); 392 } 393 394 /** 395 * Returns a {@code Collector} that produces the maximal element according 396 * to a given {@code Comparator}, described as an {@code Optional<T>}. 397 * 398 * @implSpec 399 * This produces a result equivalent to: 400 * <pre>{@code 401 * reducing(BinaryOperator.maxBy(comparator)) 402 * }</pre> 403 * 404 * @param <T> the type of the input elements 405 * @param comparator a {@code Comparator} for comparing elements 406 * @return a {@code Collector} that produces the maximal value 407 */ 408 public static <T> Collector<T, ?, Optional<T>> 409 maxBy(Comparator<? super T> comparator) { 410 return reducing(BinaryOperator.maxBy(comparator)); 411 } 412 413 /** 414 * Returns a {@code Collector} that produces the sum of a integer-valued 415 * function applied to the input elements. If no elements are present, 416 * the result is 0. 417 * 418 * @param <T> the type of the input elements 419 * @param mapper a function extracting the property to be summed 420 * @return a {@code Collector} that produces the sum of a derived property 421 */ 422 public static <T> Collector<T, ?, Integer> 423 summingInt(ToIntFunction<? super T> mapper) { 424 return new CollectorImpl<T, int[], Integer>( 425 () -> new int[1], 426 (a, t) -> { a[0] += mapper.applyAsInt(t); }, 427 (a, b) -> { a[0] += b[0]; return a; }, 428 a -> a[0], CH_NOID); 429 } 430 431 /** 432 * Returns a {@code Collector} that produces the sum of a long-valued 433 * function applied to the input elements. If no elements are present, 434 * the result is 0. 435 * 436 * @param <T> the type of the input elements 437 * @param mapper a function extracting the property to be summed 438 * @return a {@code Collector} that produces the sum of a derived property 439 */ 440 public static <T> Collector<T, ?, Long> 441 summingLong(ToLongFunction<? super T> mapper) { 442 return new CollectorImpl<T, long[], Long>( 443 () -> new long[1], 444 (a, t) -> { a[0] += mapper.applyAsLong(t); }, 445 (a, b) -> { a[0] += b[0]; return a; }, 446 a -> a[0], CH_NOID); 447 } 448 449 /** 450 * Returns a {@code Collector} that produces the sum of a double-valued 451 * function applied to the input elements. If no elements are present, 452 * the result is 0. 453 * 454 * <p>The sum returned can vary depending upon the order in which 455 * values are recorded, due to accumulated rounding error in 456 * addition of values of differing magnitudes. Values sorted by increasing 457 * absolute magnitude tend to yield more accurate results. If any recorded 458 * value is a {@code NaN} or the sum is at any point a {@code NaN} then the 459 * sum will be {@code NaN}. 460 * 461 * @param <T> the type of the input elements 462 * @param mapper a function extracting the property to be summed 463 * @return a {@code Collector} that produces the sum of a derived property 464 */ 465 public static <T> Collector<T, ?, Double> 466 summingDouble(ToDoubleFunction<? super T> mapper) { 467 return new CollectorImpl<T, double[], Double>( 468 () -> new double[1], 469 (a, t) -> { a[0] += mapper.applyAsDouble(t); }, 470 (a, b) -> { a[0] += b[0]; return a; }, 471 a -> a[0], CH_NOID); 472 } 473 474 /** 475 * Returns a {@code Collector} that produces the average of an integer-valued 476 * function applied to the input elements. If no elements are present, 477 * the result is 0. 478 * 479 * @param <T> the type of the input elements 480 * @param mapper a function extracting the property to be summed 481 * @return a {@code Collector} that produces the sum of a derived property 482 */ 483 public static <T> Collector<T, ?, Double> 484 averagingInt(ToIntFunction<? super T> mapper) { 485 return new CollectorImpl<T, long[], Double>( 486 () -> new long[2], 487 (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; }, 488 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, 489 a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID); 490 } 491 492 /** 493 * Returns a {@code Collector} that produces the average of a long-valued 494 * function applied to the input elements. If no elements are present, 495 * the result is 0. 496 * 497 * @param <T> the type of the input elements 498 * @param mapper a function extracting the property to be summed 499 * @return a {@code Collector} that produces the sum of a derived property 500 */ 501 public static <T> Collector<T, ?, Double> 502 averagingLong(ToLongFunction<? super T> mapper) { 503 return new CollectorImpl<T, long[], Double>( 504 () -> new long[2], 505 (a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; }, 506 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, 507 a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID); 508 } 509 510 /** 511 * Returns a {@code Collector} that produces the average of a double-valued 512 * function applied to the input elements. If no elements are present, 513 * the result is 0. 514 * 515 * <p>The average returned can vary depending upon the order in which 516 * values are recorded, due to accumulated rounding error in 517 * addition of values of differing magnitudes. Values sorted by increasing 518 * absolute magnitude tend to yield more accurate results. If any recorded 519 * value is a {@code NaN} or the sum is at any point a {@code NaN} then the 520 * average will be {@code NaN}. 521 * 522 * @param <T> the type of the input elements 523 * @param mapper a function extracting the property to be summed 524 * @return a {@code Collector} that produces the sum of a derived property 525 */ 526 public static <T> Collector<T, ?, Double> 527 averagingDouble(ToDoubleFunction<? super T> mapper) { 528 return new CollectorImpl<T, double[], Double>( 529 () -> new double[2], 530 (a, t) -> { a[0] += mapper.applyAsDouble(t); a[1]++; }, 531 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, 532 a -> (a[1] == 0) ? 0.0d : a[0] / a[1], CH_NOID); 533 } 534 535 /** 536 * Returns a {@code Collector} which performs a reduction of its 537 * input elements under a specified {@code BinaryOperator} using the 538 * provided identity. 539 * 540 * @apiNote 541 * The {@code reducing()} collectors are most useful when used in a 542 * multi-level reduction, downstream of {@code groupingBy} or 543 * {@code partitioningBy}. To perform a simple reduction on a stream, 544 * use {@link Stream#reduce(Object, BinaryOperator)}} instead. 545 * 546 * @param <T> element type for the input and output of the reduction 547 * @param identity the identity value for the reduction (also, the value 548 * that is returned when there are no input elements) 549 * @param op a {@code BinaryOperator<T>} used to reduce the input elements 550 * @return a {@code Collector} which implements the reduction operation 551 * 552 * @see #reducing(BinaryOperator) 553 * @see #reducing(Object, Function, BinaryOperator) 554 */ 555 public static <T> Collector<T, ?, T> 556 reducing(T identity, BinaryOperator<T> op) { 557 return new CollectorImpl<>( 558 boxSupplier(identity), 559 (a, t) -> { a[0] = op.apply(a[0], t); }, 560 (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; }, 561 a -> a[0], 562 CH_NOID); 563 } 564 565 @SuppressWarnings("unchecked") 566 private static <T> Supplier<T[]> boxSupplier(T identity) { 567 return () -> (T[]) new Object[] { identity }; 568 } 569 570 /** 571 * Returns a {@code Collector} which performs a reduction of its 572 * input elements under a specified {@code BinaryOperator}. The result 573 * is described as an {@code Optional<T>}. 574 * 575 * @apiNote 576 * The {@code reducing()} collectors are most useful when used in a 577 * multi-level reduction, downstream of {@code groupingBy} or 578 * {@code partitioningBy}. To perform a simple reduction on a stream, 579 * use {@link Stream#reduce(BinaryOperator)} instead. 580 * 581 * <p>For example, given a stream of {@code Person}, to calculate tallest 582 * person in each city: 583 * <pre>{@code 584 * Comparator<Person> byHeight = Comparator.comparing(Person::getHeight); 585 * Map<City, Person> tallestByCity 586 * = people.stream().collect(groupingBy(Person::getCity, reducing(BinaryOperator.maxBy(byHeight)))); 587 * }</pre> 588 * 589 * @param <T> element type for the input and output of the reduction 590 * @param op a {@code BinaryOperator<T>} used to reduce the input elements 591 * @return a {@code Collector} which implements the reduction operation 592 * 593 * @see #reducing(Object, BinaryOperator) 594 * @see #reducing(Object, Function, BinaryOperator) 595 */ 596 public static <T> Collector<T, ?, Optional<T>> 597 reducing(BinaryOperator<T> op) { 598 class OptionalBox implements Consumer<T> { 599 T value = null; 600 boolean present = false; 601 602 @Override 603 public void accept(T t) { 604 if (present) { 605 value = op.apply(value, t); 606 } 607 else { 608 value = t; 609 present = true; 610 } 611 } 612 } 613 614 return new CollectorImpl<T, OptionalBox, Optional<T>>( 615 OptionalBox::new, OptionalBox::accept, 616 (a, b) -> { if (b.present) a.accept(b.value); return a; }, 617 a -> Optional.ofNullable(a.value), CH_NOID); 618 } 619 620 /** 621 * Returns a {@code Collector} which performs a reduction of its 622 * input elements under a specified mapping function and 623 * {@code BinaryOperator}. This is a generalization of 624 * {@link #reducing(Object, BinaryOperator)} which allows a transformation 625 * of the elements before reduction. 626 * 627 * @apiNote 628 * The {@code reducing()} collectors are most useful when used in a 629 * multi-level reduction, downstream of {@code groupingBy} or 630 * {@code partitioningBy}. To perform a simple map-reduce on a stream, 631 * use {@link Stream#map(Function)} and {@link Stream#reduce(Object, BinaryOperator)} 632 * instead. 633 * 634 * <p>For example, given a stream of {@code Person}, to calculate the longest 635 * last name of residents in each city: 636 * <pre>{@code 637 * Comparator<String> byLength = Comparator.comparing(String::length); 638 * Map<City, String> longestLastNameByCity 639 * = people.stream().collect(groupingBy(Person::getCity, 640 * reducing(Person::getLastName, BinaryOperator.maxBy(byLength)))); 641 * }</pre> 642 * 643 * @param <T> the type of the input elements 644 * @param <U> the type of the mapped values 645 * @param identity the identity value for the reduction (also, the value 646 * that is returned when there are no input elements) 647 * @param mapper a mapping function to apply to each input value 648 * @param op a {@code BinaryOperator<U>} used to reduce the mapped values 649 * @return a {@code Collector} implementing the map-reduce operation 650 * 651 * @see #reducing(Object, BinaryOperator) 652 * @see #reducing(BinaryOperator) 653 */ 654 public static <T, U> 655 Collector<T, ?, U> reducing(U identity, 656 Function<? super T, ? extends U> mapper, 657 BinaryOperator<U> op) { 658 return new CollectorImpl<>( 659 boxSupplier(identity), 660 (a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); }, 661 (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; }, 662 a -> a[0], CH_NOID); 663 } 664 665 /** 666 * Returns a {@code Collector} implementing a "group by" operation on 667 * input elements of type {@code T}, grouping elements according to a 668 * classification function, and returning the results in a {@code Map}. 669 * 670 * <p>The classification function maps elements to some key type {@code K}. 671 * The collector produces a {@code Map<K, List<T>>} whose keys are the 672 * values resulting from applying the classification function to the input 673 * elements, and whose corresponding values are {@code List}s containing the 674 * input elements which map to the associated key under the classification 675 * function. 676 * 677 * <p>There are no guarantees on the type, mutability, serializability, or 678 * thread-safety of the {@code Map} or {@code List} objects returned. 679 * @implSpec 680 * This produces a result similar to: 681 * <pre>{@code 682 * groupingBy(classifier, toList()); 683 * }</pre> 684 * 685 * @param <T> the type of the input elements 686 * @param <K> the type of the keys 687 * @param classifier the classifier function mapping input elements to keys 688 * @return a {@code Collector} implementing the group-by operation 689 * 690 * @see #groupingBy(Function, Collector) 691 * @see #groupingBy(Function, Supplier, Collector) 692 * @see #groupingByConcurrent(Function) 693 */ 694 public static <T, K> Collector<T, ?, Map<K, List<T>>> 695 groupingBy(Function<? super T, ? extends K> classifier) { 696 return groupingBy(classifier, toList()); 697 } 698 699 /** 700 * Returns a {@code Collector} implementing a cascaded "group by" operation 701 * on input elements of type {@code T}, grouping elements according to a 702 * classification function, and then performing a reduction operation on 703 * the values associated with a given key using the specified downstream 704 * {@code Collector}. 705 * 706 * <p>The classification function maps elements to some key type {@code K}. 707 * The downstream collector operates on elements of type {@code T} and 708 * produces a result of type {@code D}. The resulting collector produces a 709 * {@code Map<K, D>}. 710 * 711 * <p>There are no guarantees on the type, mutability, 712 * serializability, or thread-safety of the {@code Map} returned. 713 * 714 * <p>For example, to compute the set of last names of people in each city: 715 * <pre>{@code 716 * Map<City, Set<String>> namesByCity 717 * = people.stream().collect(groupingBy(Person::getCity, 718 * mapping(Person::getLastName, toSet()))); 719 * }</pre> 720 * 721 * @param <T> the type of the input elements 722 * @param <K> the type of the keys 723 * @param <A> the intermediate accumulation type of the downstream collector 724 * @param <D> the result type of the downstream reduction 725 * @param classifier a classifier function mapping input elements to keys 726 * @param downstream a {@code Collector} implementing the downstream reduction 727 * @return a {@code Collector} implementing the cascaded group-by operation 728 * @see #groupingBy(Function) 729 * 730 * @see #groupingBy(Function, Supplier, Collector) 731 * @see #groupingByConcurrent(Function, Collector) 732 */ 733 public static <T, K, A, D> 734 Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, 735 Collector<? super T, A, D> downstream) { 736 return groupingBy(classifier, HashMap::new, downstream); 737 } 738 739 /** 740 * Returns a {@code Collector} implementing a cascaded "group by" operation 741 * on input elements of type {@code T}, grouping elements according to a 742 * classification function, and then performing a reduction operation on 743 * the values associated with a given key using the specified downstream 744 * {@code Collector}. The {@code Map} produced by the Collector is created 745 * with the supplied factory function. 746 * 747 * <p>The classification function maps elements to some key type {@code K}. 748 * The downstream collector operates on elements of type {@code T} and 749 * produces a result of type {@code D}. The resulting collector produces a 750 * {@code Map<K, D>}. 751 * 752 * <p>For example, to compute the set of last names of people in each city, 753 * where the city names are sorted: 754 * <pre>{@code 755 * Map<City, Set<String>> namesByCity 756 * = people.stream().collect(groupingBy(Person::getCity, TreeMap::new, 757 * mapping(Person::getLastName, toSet()))); 758 * }</pre> 759 * 760 * @param <T> the type of the input elements 761 * @param <K> the type of the keys 762 * @param <A> the intermediate accumulation type of the downstream collector 763 * @param <D> the result type of the downstream reduction 764 * @param <M> the type of the resulting {@code Map} 765 * @param classifier a classifier function mapping input elements to keys 766 * @param downstream a {@code Collector} implementing the downstream reduction 767 * @param mapFactory a function which, when called, produces a new empty 768 * {@code Map} of the desired type 769 * @return a {@code Collector} implementing the cascaded group-by operation 770 * 771 * @see #groupingBy(Function, Collector) 772 * @see #groupingBy(Function) 773 * @see #groupingByConcurrent(Function, Supplier, Collector) 774 */ 775 public static <T, K, D, A, M extends Map<K, D>> 776 Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier, 777 Supplier<M> mapFactory, 778 Collector<? super T, A, D> downstream) { 779 Supplier<A> downstreamSupplier = downstream.supplier(); 780 BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator(); 781 BiConsumer<Map<K, A>, T> accumulator = (m, t) -> { 782 K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); 783 A container = m.computeIfAbsent(key, k -> downstreamSupplier.get()); 784 downstreamAccumulator.accept(container, t); 785 }; 786 BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner()); 787 @SuppressWarnings("unchecked") 788 Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory; 789 790 if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { 791 return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID); 792 } 793 else { 794 @SuppressWarnings("unchecked") 795 Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher(); 796 Function<Map<K, A>, M> finisher = intermediate -> { 797 intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v)); 798 @SuppressWarnings("unchecked") 799 M castResult = (M) intermediate; 800 return castResult; 801 }; 802 return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID); 803 } 804 } 805 806 /** 807 * Returns a concurrent {@code Collector} implementing a "group by" 808 * operation on input elements of type {@code T}, grouping elements 809 * according to a classification function. 810 * 811 * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and 812 * {@link Collector.Characteristics#UNORDERED unordered} Collector. 813 * 814 * <p>The classification function maps elements to some key type {@code K}. 815 * The collector produces a {@code ConcurrentMap<K, List<T>>} whose keys are the 816 * values resulting from applying the classification function to the input 817 * elements, and whose corresponding values are {@code List}s containing the 818 * input elements which map to the associated key under the classification 819 * function. 820 * 821 * <p>There are no guarantees on the type, mutability, or serializability 822 * of the {@code Map} or {@code List} objects returned, or of the 823 * thread-safety of the {@code List} objects returned. 824 * @implSpec 825 * This produces a result similar to: 826 * <pre>{@code 827 * groupingByConcurrent(classifier, toList()); 828 * }</pre> 829 * 830 * @param <T> the type of the input elements 831 * @param <K> the type of the keys 832 * @param classifier a classifier function mapping input elements to keys 833 * @return a {@code Collector} implementing the group-by operation 834 * 835 * @see #groupingBy(Function) 836 * @see #groupingByConcurrent(Function, Collector) 837 * @see #groupingByConcurrent(Function, Supplier, Collector) 838 */ 839 public static <T, K> 840 Collector<T, ?, ConcurrentMap<K, List<T>>> 841 groupingByConcurrent(Function<? super T, ? extends K> classifier) { 842 return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList()); 843 } 844 845 /** 846 * Returns a concurrent {@code Collector} implementing a cascaded "group by" 847 * operation on input elements of type {@code T}, grouping elements 848 * according to a classification function, and then performing a reduction 849 * operation on the values associated with a given key using the specified 850 * downstream {@code Collector}. 851 * 852 * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and 853 * {@link Collector.Characteristics#UNORDERED unordered} Collector. 854 * 855 * <p>The classification function maps elements to some key type {@code K}. 856 * The downstream collector operates on elements of type {@code T} and 857 * produces a result of type {@code D}. The resulting collector produces a 858 * {@code Map<K, D>}. 859 * 860 * <p>For example, to compute the set of last names of people in each city, 861 * where the city names are sorted: 862 * <pre>{@code 863 * ConcurrentMap<City, Set<String>> namesByCity 864 * = people.stream().collect(groupingByConcurrent(Person::getCity, ConcurrentSkipListMap::new, 865 * mapping(Person::getLastName, toSet()))); 866 * }</pre> 867 * 868 * @param <T> the type of the input elements 869 * @param <K> the type of the keys 870 * @param <A> the intermediate accumulation type of the downstream collector 871 * @param <D> the result type of the downstream reduction 872 * @param classifier a classifier function mapping input elements to keys 873 * @param downstream a {@code Collector} implementing the downstream reduction 874 * @return a {@code Collector} implementing the cascaded group-by operation 875 * 876 * @see #groupingBy(Function, Collector) 877 * @see #groupingByConcurrent(Function) 878 * @see #groupingByConcurrent(Function, Supplier, Collector) 879 */ 880 public static <T, K, A, D> 881 Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier, 882 Collector<? super T, A, D> downstream) { 883 return groupingByConcurrent(classifier, ConcurrentHashMap::new, downstream); 884 } 885 886 /** 887 * Returns a concurrent {@code Collector} implementing a cascaded "group by" 888 * operation on input elements of type {@code T}, grouping elements 889 * according to a classification function, and then performing a reduction 890 * operation on the values associated with a given key using the specified 891 * downstream {@code Collector}. The {@code ConcurrentMap} produced by the 892 * Collector is created with the supplied factory function. 893 * 894 * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and 895 * {@link Collector.Characteristics#UNORDERED unordered} Collector. 896 * 897 * <p>The classification function maps elements to some key type {@code K}. 898 * The downstream collector operates on elements of type {@code T} and 899 * produces a result of type {@code D}. The resulting collector produces a 900 * {@code Map<K, D>}. 901 * 902 * <p>For example, to compute the set of last names of people in each city, 903 * where the city names are sorted: 904 * <pre>{@code 905 * ConcurrentMap<City, Set<String>> namesByCity 906 * = people.stream().collect(groupingBy(Person::getCity, ConcurrentSkipListMap::new, 907 * mapping(Person::getLastName, toSet()))); 908 * }</pre> 909 * 910 * 911 * @param <T> the type of the input elements 912 * @param <K> the type of the keys 913 * @param <A> the intermediate accumulation type of the downstream collector 914 * @param <D> the result type of the downstream reduction 915 * @param <M> the type of the resulting {@code ConcurrentMap} 916 * @param classifier a classifier function mapping input elements to keys 917 * @param downstream a {@code Collector} implementing the downstream reduction 918 * @param mapFactory a function which, when called, produces a new empty 919 * {@code ConcurrentMap} of the desired type 920 * @return a {@code Collector} implementing the cascaded group-by operation 921 * 922 * @see #groupingByConcurrent(Function) 923 * @see #groupingByConcurrent(Function, Collector) 924 * @see #groupingBy(Function, Supplier, Collector) 925 */ 926 public static <T, K, A, D, M extends ConcurrentMap<K, D>> 927 Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier, 928 Supplier<M> mapFactory, 929 Collector<? super T, A, D> downstream) { 930 Supplier<A> downstreamSupplier = downstream.supplier(); 931 BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator(); 932 BinaryOperator<ConcurrentMap<K, A>> merger = Collectors.<K, A, ConcurrentMap<K, A>>mapMerger(downstream.combiner()); 933 @SuppressWarnings("unchecked") 934 Supplier<ConcurrentMap<K, A>> mangledFactory = (Supplier<ConcurrentMap<K, A>>) mapFactory; 935 BiConsumer<ConcurrentMap<K, A>, T> accumulator; 936 if (downstream.characteristics().contains(Collector.Characteristics.CONCURRENT)) { 937 accumulator = (m, t) -> { 938 K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); 939 A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get()); 940 downstreamAccumulator.accept(resultContainer, t); 941 }; 942 } 943 else { 944 accumulator = (m, t) -> { 945 K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); 946 A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get()); 947 synchronized (resultContainer) { 948 downstreamAccumulator.accept(resultContainer, t); 949 } 950 }; 951 } 952 953 if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { 954 return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_CONCURRENT_ID); 955 } 956 else { 957 @SuppressWarnings("unchecked") 958 Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher(); 959 Function<ConcurrentMap<K, A>, M> finisher = intermediate -> { 960 intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v)); 961 @SuppressWarnings("unchecked") 962 M castResult = (M) intermediate; 963 return castResult; 964 }; 965 return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID); 966 } 967 } 968 969 /** 970 * Returns a {@code Collector} which partitions the input elements according 971 * to a {@code Predicate}, and organizes them into a 972 * {@code Map<Boolean, List<T>>}. 973 * 974 * There are no guarantees on the type, mutability, 975 * serializability, or thread-safety of the {@code Map} returned. 976 * 977 * @param <T> the type of the input elements 978 * @param predicate a predicate used for classifying input elements 979 * @return a {@code Collector} implementing the partitioning operation 980 * 981 * @see #partitioningBy(Predicate, Collector) 982 */ 983 public static <T> 984 Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) { 985 return partitioningBy(predicate, toList()); 986 } 987 988 /** 989 * Returns a {@code Collector} which partitions the input elements according 990 * to a {@code Predicate}, reduces the values in each partition according to 991 * another {@code Collector}, and organizes them into a 992 * {@code Map<Boolean, D>} whose values are the result of the downstream 993 * reduction. 994 * 995 * <p>There are no guarantees on the type, mutability, 996 * serializability, or thread-safety of the {@code Map} returned. 997 * 998 * @param <T> the type of the input elements 999 * @param <A> the intermediate accumulation type of the downstream collector 1000 * @param <D> the result type of the downstream reduction 1001 * @param predicate a predicate used for classifying input elements 1002 * @param downstream a {@code Collector} implementing the downstream 1003 * reduction 1004 * @return a {@code Collector} implementing the cascaded partitioning 1005 * operation 1006 * 1007 * @see #partitioningBy(Predicate) 1008 */ 1009 public static <T, D, A> 1010 Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate, 1011 Collector<? super T, A, D> downstream) { 1012 @SuppressWarnings("unchecked") 1013 BiConsumer<D, ? super T> downstreamAccumulator = (BiConsumer<D, ? super T>) downstream.accumulator(); 1014 BiConsumer<Map<Boolean, A>, T> accumulator = (result, t) -> { 1015 Partition<D> asPartition = ((Partition<D>) result); 1016 downstreamAccumulator.accept(predicate.test(t) ? asPartition.forTrue : asPartition.forFalse, t); 1017 }; 1018 BinaryOperator<A> op = downstream.combiner(); 1019 BinaryOperator<Map<Boolean, A>> merger = (m1, m2) -> { 1020 Partition<A> left = (Partition<A>) m1; 1021 Partition<A> right = (Partition<A>) m2; 1022 return new Partition<>(op.apply(left.forTrue, right.forTrue), 1023 op.apply(left.forFalse, right.forFalse)); 1024 }; 1025 Supplier<Map<Boolean, A>> supplier = () -> new Partition<>(downstream.supplier().get(), 1026 downstream.supplier().get()); 1027 if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { 1028 return new CollectorImpl<>(supplier, accumulator, merger, CH_ID); 1029 } 1030 else { 1031 Function<Map<Boolean, A>, Map<Boolean, D>> finisher = (Map<Boolean, A> par) -> { 1032 Partition<A> asAPartition = (Partition<A>) par; 1033 return new Partition<>(downstream.finisher().apply(asAPartition.forTrue), 1034 downstream.finisher().apply(asAPartition.forFalse)); 1035 }; 1036 return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID); 1037 } 1038 } 1039 1040 /** 1041 * Returns a {@code Collector} that accumulate elements into a 1042 * {@code Map} whose keys and values are the result of applying the provided 1043 * mapping functions to the input elements. 1044 * 1045 * <p>If the mapped keys contains duplicates (according to 1046 * {@link Object#equals(Object)}), an {@code IllegalStateException} is 1047 * thrown when the collection operation is performed. If the mapped keys 1048 * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)} 1049 * instead. 1050 * 1051 * @apiNote 1052 * It is common for either the key or the value to be the input elements. 1053 * In this case, the utility method 1054 * {@link java.util.function.Function#identity()} may be helpful. 1055 * For example, the following produces a {@code Map} mapping 1056 * students to their grade point average: 1057 * <pre>{@code 1058 * Map<Student, Double> studentToGPA 1059 * students.stream().collect(toMap(Functions.identity(), 1060 * student -> computeGPA(student))); 1061 * }</pre> 1062 * And the following produces a {@code Map} mapping a unique identifier to 1063 * students: 1064 * <pre>{@code 1065 * Map<String, Student> studentIdToStudent 1066 * students.stream().collect(toMap(Student::getId, 1067 * Functions.identity()); 1068 * }</pre> 1069 * 1070 * @param <T> the type of the input elements 1071 * @param <K> the output type of the key mapping function 1072 * @param <U> the output type of the value mapping function 1073 * @param keyMapper a mapping function to produce keys 1074 * @param valueMapper a mapping function to produce values 1075 * @return a {@code Collector} which collects elements into a {@code Map} 1076 * whose keys and values are the result of applying mapping functions to 1077 * the input elements 1078 * 1079 * @see #toMap(Function, Function, BinaryOperator) 1080 * @see #toMap(Function, Function, BinaryOperator, Supplier) 1081 * @see #toConcurrentMap(Function, Function) 1082 */ 1083 public static <T, K, U> 1084 Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, 1085 Function<? super T, ? extends U> valueMapper) { 1086 return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new); 1087 } 1088 1089 /** 1090 * Returns a {@code Collector} that accumulate elements into a 1091 * {@code Map} whose keys and values are the result of applying the provided 1092 * mapping functions to the input elements. 1093 * 1094 * <p>If the mapped 1095 * keys contains duplicates (according to {@link Object#equals(Object)}), 1096 * the value mapping function is applied to each equal element, and the 1097 * results are merged using the provided merging function. 1098 * 1099 * @apiNote 1100 * There are multiple ways to deal with collisions between multiple elements 1101 * mapping to the same key. The other forms of {@code toMap} simply use 1102 * a merge function that throws unconditionally, but you can easily write 1103 * more flexible merge policies. For example, if you have a stream 1104 * of {@code Person}, and you want to produce a "phone book" mapping name to 1105 * address, but it is possible that two persons have the same name, you can 1106 * do as follows to gracefully deals with these collisions, and produce a 1107 * {@code Map} mapping names to a concatenated list of addresses: 1108 * <pre>{@code 1109 * Map<String, String> phoneBook 1110 * people.stream().collect(toMap(Person::getName, 1111 * Person::getAddress, 1112 * (s, a) -> s + ", " + a)); 1113 * }</pre> 1114 * 1115 * @param <T> the type of the input elements 1116 * @param <K> the output type of the key mapping function 1117 * @param <U> the output type of the value mapping function 1118 * @param keyMapper a mapping function to produce keys 1119 * @param valueMapper a mapping function to produce values 1120 * @param mergeFunction a merge function, used to resolve collisions between 1121 * values associated with the same key, as supplied 1122 * to {@link Map#merge(Object, Object, BiFunction)} 1123 * @return a {@code Collector} which collects elements into a {@code Map} 1124 * whose keys are the result of applying a key mapping function to the input 1125 * elements, and whose values are the result of applying a value mapping 1126 * function to all input elements equal to the key and combining them 1127 * using the merge function 1128 * 1129 * @see #toMap(Function, Function) 1130 * @see #toMap(Function, Function, BinaryOperator, Supplier) 1131 * @see #toConcurrentMap(Function, Function, BinaryOperator) 1132 */ 1133 public static <T, K, U> 1134 Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, 1135 Function<? super T, ? extends U> valueMapper, 1136 BinaryOperator<U> mergeFunction) { 1137 return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); 1138 } 1139 1140 /** 1141 * Returns a {@code Collector} that accumulate elements into a 1142 * {@code Map} whose keys and values are the result of applying the provided 1143 * mapping functions to the input elements. 1144 * 1145 * <p>If the mapped 1146 * keys contains duplicates (according to {@link Object#equals(Object)}), 1147 * the value mapping function is applied to each equal element, and the 1148 * results are merged using the provided merging function. The {@code Map} 1149 * is created by a provided supplier function. 1150 * 1151 * @param <T> the type of the input elements 1152 * @param <K> the output type of the key mapping function 1153 * @param <U> the output type of the value mapping function 1154 * @param <M> the type of the resulting {@code Map} 1155 * @param keyMapper a mapping function to produce keys 1156 * @param valueMapper a mapping function to produce values 1157 * @param mergeFunction a merge function, used to resolve collisions between 1158 * values associated with the same key, as supplied 1159 * to {@link Map#merge(Object, Object, BiFunction)} 1160 * @param mapSupplier a function which returns a new, empty {@code Map} into 1161 * which the results will be inserted 1162 * @return a {@code Collector} which collects elements into a {@code Map} 1163 * whose keys are the result of applying a key mapping function to the input 1164 * elements, and whose values are the result of applying a value mapping 1165 * function to all input elements equal to the key and combining them 1166 * using the merge function 1167 * 1168 * @see #toMap(Function, Function) 1169 * @see #toMap(Function, Function, BinaryOperator) 1170 * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier) 1171 */ 1172 public static <T, K, U, M extends Map<K, U>> 1173 Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper, 1174 Function<? super T, ? extends U> valueMapper, 1175 BinaryOperator<U> mergeFunction, 1176 Supplier<M> mapSupplier) { 1177 BiConsumer<M, T> accumulator 1178 = (map, element) -> map.merge(keyMapper.apply(element), 1179 valueMapper.apply(element), mergeFunction); 1180 return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID); 1181 } 1182 1183 /** 1184 * Returns a {@code Collector} that accumulate elements into a 1185 * {@code ConcurrentMap} whose keys and values are the result of applying 1186 * the provided mapping functions to the input elements. 1187 * 1188 * <p>If the mapped keys contains duplicates (according to 1189 * {@link Object#equals(Object)}), an {@code IllegalStateException} is 1190 * thrown when the collection operation is performed. If the mapped keys 1191 * may have duplicates, use 1192 * {@link #toConcurrentMap(Function, Function, BinaryOperator)} instead. 1193 * 1194 * @apiNote 1195 * It is common for either the key or the value to be the input elements. 1196 * In this case, the utility method 1197 * {@link java.util.function.Function#identity()} may be helpful. 1198 * For example, the following produces a {@code Map} mapping 1199 * students to their grade point average: 1200 * <pre>{@code 1201 * Map<Student, Double> studentToGPA 1202 * students.stream().collect(toMap(Functions.identity(), 1203 * student -> computeGPA(student))); 1204 * }</pre> 1205 * And the following produces a {@code Map} mapping a unique identifier to 1206 * students: 1207 * <pre>{@code 1208 * Map<String, Student> studentIdToStudent 1209 * students.stream().collect(toConcurrentMap(Student::getId, 1210 * Functions.identity()); 1211 * }</pre> 1212 * 1213 * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and 1214 * {@link Collector.Characteristics#UNORDERED unordered} Collector. 1215 * 1216 * @param <T> the type of the input elements 1217 * @param <K> the output type of the key mapping function 1218 * @param <U> the output type of the value mapping function 1219 * @param keyMapper the mapping function to produce keys 1220 * @param valueMapper the mapping function to produce values 1221 * @return a concurrent {@code Collector} which collects elements into a 1222 * {@code ConcurrentMap} whose keys are the result of applying a key mapping 1223 * function to the input elements, and whose values are the result of 1224 * applying a value mapping function to the input elements 1225 * 1226 * @see #toMap(Function, Function) 1227 * @see #toConcurrentMap(Function, Function, BinaryOperator) 1228 * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier) 1229 */ 1230 public static <T, K, U> 1231 Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper, 1232 Function<? super T, ? extends U> valueMapper) { 1233 return toConcurrentMap(keyMapper, valueMapper, throwingMerger(), ConcurrentHashMap::new); 1234 } 1235 1236 /** 1237 * Returns a {@code Collector} that accumulate elements into a 1238 * {@code ConcurrentMap} whose keys and values are the result of applying 1239 * the provided mapping functions to the input elements. 1240 * 1241 * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}), 1242 * the value mapping function is applied to each equal element, and the 1243 * results are merged using the provided merging function. 1244 * 1245 * @apiNote 1246 * There are multiple ways to deal with collisions between multiple elements 1247 * mapping to the same key. The other forms of {@code toConcurrentMap} simply use 1248 * a merge function that throws unconditionally, but you can easily write 1249 * more flexible merge policies. For example, if you have a stream 1250 * of {@code Person}, and you want to produce a "phone book" mapping name to 1251 * address, but it is possible that two persons have the same name, you can 1252 * do as follows to gracefully deals with these collisions, and produce a 1253 * {@code Map} mapping names to a concatenated list of addresses: 1254 * <pre>{@code 1255 * Map<String, String> phoneBook 1256 * people.stream().collect(toConcurrentMap(Person::getName, 1257 * Person::getAddress, 1258 * (s, a) -> s + ", " + a)); 1259 * }</pre> 1260 * 1261 * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and 1262 * {@link Collector.Characteristics#UNORDERED unordered} Collector. 1263 * 1264 * @param <T> the type of the input elements 1265 * @param <K> the output type of the key mapping function 1266 * @param <U> the output type of the value mapping function 1267 * @param keyMapper a mapping function to produce keys 1268 * @param valueMapper a mapping function to produce values 1269 * @param mergeFunction a merge function, used to resolve collisions between 1270 * values associated with the same key, as supplied 1271 * to {@link Map#merge(Object, Object, BiFunction)} 1272 * @return a concurrent {@code Collector} which collects elements into a 1273 * {@code ConcurrentMap} whose keys are the result of applying a key mapping 1274 * function to the input elements, and whose values are the result of 1275 * applying a value mapping function to all input elements equal to the key 1276 * and combining them using the merge function 1277 * 1278 * @see #toConcurrentMap(Function, Function) 1279 * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier) 1280 * @see #toMap(Function, Function, BinaryOperator) 1281 */ 1282 public static <T, K, U> 1283 Collector<T, ?, ConcurrentMap<K,U>> 1284 toConcurrentMap(Function<? super T, ? extends K> keyMapper, 1285 Function<? super T, ? extends U> valueMapper, 1286 BinaryOperator<U> mergeFunction) { 1287 return toConcurrentMap(keyMapper, valueMapper, mergeFunction, ConcurrentHashMap::new); 1288 } 1289 1290 /** 1291 * Returns a {@code Collector} that accumulate elements into a 1292 * {@code ConcurrentMap} whose keys and values are the result of applying 1293 * the provided mapping functions to the input elements. 1294 * 1295 * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}), 1296 * the value mapping function is applied to each equal element, and the 1297 * results are merged using the provided merging function. The 1298 * {@code ConcurrentMap} is created by a provided supplier function. 1299 * 1300 * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and 1301 * {@link Collector.Characteristics#UNORDERED unordered} Collector. 1302 * 1303 * @param <T> the type of the input elements 1304 * @param <K> the output type of the key mapping function 1305 * @param <U> the output type of the value mapping function 1306 * @param <M> the type of the resulting {@code ConcurrentMap} 1307 * @param keyMapper a mapping function to produce keys 1308 * @param valueMapper a mapping function to produce values 1309 * @param mergeFunction a merge function, used to resolve collisions between 1310 * values associated with the same key, as supplied 1311 * to {@link Map#merge(Object, Object, BiFunction)} 1312 * @param mapSupplier a function which returns a new, empty {@code Map} into 1313 * which the results will be inserted 1314 * @return a concurrent {@code Collector} which collects elements into a 1315 * {@code ConcurrentMap} whose keys are the result of applying a key mapping 1316 * function to the input elements, and whose values are the result of 1317 * applying a value mapping function to all input elements equal to the key 1318 * and combining them using the merge function 1319 * 1320 * @see #toConcurrentMap(Function, Function) 1321 * @see #toConcurrentMap(Function, Function, BinaryOperator) 1322 * @see #toMap(Function, Function, BinaryOperator, Supplier) 1323 */ 1324 public static <T, K, U, M extends ConcurrentMap<K, U>> 1325 Collector<T, ?, M> toConcurrentMap(Function<? super T, ? extends K> keyMapper, 1326 Function<? super T, ? extends U> valueMapper, 1327 BinaryOperator<U> mergeFunction, 1328 Supplier<M> mapSupplier) { 1329 BiConsumer<M, T> accumulator 1330 = (map, element) -> map.merge(keyMapper.apply(element), 1331 valueMapper.apply(element), mergeFunction); 1332 return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_CONCURRENT_ID); 1333 } 1334 1335 /** 1336 * Returns a {@code Collector} which applies an {@code int}-producing 1337 * mapping function to each input element, and returns summary statistics 1338 * for the resulting values. 1339 * 1340 * @param <T> the type of the input elements 1341 * @param mapper a mapping function to apply to each element 1342 * @return a {@code Collector} implementing the summary-statistics reduction 1343 * 1344 * @see #summarizingDouble(ToDoubleFunction) 1345 * @see #summarizingLong(ToLongFunction) 1346 */ 1347 public static <T> 1348 Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) { 1349 return new CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>( 1350 IntSummaryStatistics::new, 1351 (r, t) -> r.accept(mapper.applyAsInt(t)), 1352 (l, r) -> { l.combine(r); return l; }, CH_ID); 1353 } 1354 1355 /** 1356 * Returns a {@code Collector} which applies an {@code long}-producing 1357 * mapping function to each input element, and returns summary statistics 1358 * for the resulting values. 1359 * 1360 * @param <T> the type of the input elements 1361 * @param mapper the mapping function to apply to each element 1362 * @return a {@code Collector} implementing the summary-statistics reduction 1363 * 1364 * @see #summarizingDouble(ToDoubleFunction) 1365 * @see #summarizingInt(ToIntFunction) 1366 */ 1367 public static <T> 1368 Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) { 1369 return new CollectorImpl<T, LongSummaryStatistics, LongSummaryStatistics>( 1370 LongSummaryStatistics::new, 1371 (r, t) -> r.accept(mapper.applyAsLong(t)), 1372 (l, r) -> { l.combine(r); return l; }, CH_ID); 1373 } 1374 1375 /** 1376 * Returns a {@code Collector} which applies an {@code double}-producing 1377 * mapping function to each input element, and returns summary statistics 1378 * for the resulting values. 1379 * 1380 * @param <T> the type of the input elements 1381 * @param mapper a mapping function to apply to each element 1382 * @return a {@code Collector} implementing the summary-statistics reduction 1383 * 1384 * @see #summarizingLong(ToLongFunction) 1385 * @see #summarizingInt(ToIntFunction) 1386 */ 1387 public static <T> 1388 Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) { 1389 return new CollectorImpl<T, DoubleSummaryStatistics, DoubleSummaryStatistics>( 1390 DoubleSummaryStatistics::new, 1391 (r, t) -> r.accept(mapper.applyAsDouble(t)), 1392 (l, r) -> { l.combine(r); return l; }, CH_ID); 1393 } 1394 1395 /** 1396 * Implementation class used by partitioningBy. 1397 */ 1398 private static final class Partition<T> 1399 extends AbstractMap<Boolean, T> 1400 implements Map<Boolean, T> { 1401 final T forTrue; 1402 final T forFalse; 1403 1404 Partition(T forTrue, T forFalse) { 1405 this.forTrue = forTrue; 1406 this.forFalse = forFalse; 1407 } 1408 1409 @Override 1410 public Set<Map.Entry<Boolean, T>> entrySet() { 1411 return new AbstractSet<Map.Entry<Boolean, T>>() { 1412 @Override 1413 public Iterator<Map.Entry<Boolean, T>> iterator() { 1414 Map.Entry<Boolean, T> falseEntry = new SimpleImmutableEntry<>(false, forFalse); 1415 Map.Entry<Boolean, T> trueEntry = new SimpleImmutableEntry<>(true, forTrue); 1416 return Arrays.asList(falseEntry, trueEntry).iterator(); 1417 } 1418 1419 @Override 1420 public int size() { 1421 return 2; 1422 } 1423 }; 1424 } 1425 } 1426 }