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