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