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