99 *
100 * }</pre>
101 *
102 * @since 1.8
103 */
104 public final class Collectors {
105
106 static final Set<Collector.Characteristics> CH_CONCURRENT_ID
107 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
108 Collector.Characteristics.UNORDERED,
109 Collector.Characteristics.IDENTITY_FINISH));
110 static final Set<Collector.Characteristics> CH_CONCURRENT_NOID
111 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
112 Collector.Characteristics.UNORDERED));
113 static final Set<Collector.Characteristics> CH_ID
114 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
115 static final Set<Collector.Characteristics> CH_UNORDERED_ID
116 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
117 Collector.Characteristics.IDENTITY_FINISH));
118 static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
119
120 private Collectors() { }
121
122 /**
123 * Construct an {@code IllegalStateException} with appropriate message.
124 *
125 * @param k the duplicate key
126 * @param u 1st value to be accumulated/merged
127 * @param v 2nd value to be accumulated/merged
128 */
129 private static IllegalStateException duplicateKeyException(
130 Object k, Object u, Object v) {
131 return new IllegalStateException(String.format(
132 "Duplicate key %s (attempted merging values %s and %s)",
133 k, u, v));
134 }
135
136 /**
137 * {@code BinaryOperator<Map>} that merges the contents of its right
138 * argument into its left argument, throwing {@code IllegalStateException}
262 }
263
264 /**
265 * Returns a {@code Collector} that accumulates the input elements into a
266 * new {@code List}. There are no guarantees on the type, mutability,
267 * serializability, or thread-safety of the {@code List} returned; if more
268 * control over the returned {@code List} is required, use {@link #toCollection(Supplier)}.
269 *
270 * @param <T> the type of the input elements
271 * @return a {@code Collector} which collects all the input elements into a
272 * {@code List}, in encounter order
273 */
274 public static <T>
275 Collector<T, ?, List<T>> toList() {
276 return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
277 (left, right) -> { left.addAll(right); return left; },
278 CH_ID);
279 }
280
281 /**
282 * Returns a {@code Collector} that accumulates the input elements into a
283 * new {@code Set}. There are no guarantees on the type, mutability,
284 * serializability, or thread-safety of the {@code Set} returned; if more
285 * control over the returned {@code Set} is required, use
286 * {@link #toCollection(Supplier)}.
287 *
288 * <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
289 * Collector.
290 *
291 * @param <T> the type of the input elements
292 * @return a {@code Collector} which collects all the input elements into a
293 * {@code Set}
294 */
295 public static <T>
296 Collector<T, ?, Set<T>> toSet() {
297 return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
298 (left, right) -> {
299 if (left.size() < right.size()) {
300 right.addAll(left); return right;
301 } else {
302 left.addAll(right); return left;
303 }
304 },
305 CH_UNORDERED_ID);
306 }
307
308 /**
309 * Returns a {@code Collector} that concatenates the input elements into a
310 * {@code String}, in encounter order.
311 *
312 * @return a {@code Collector} that concatenates the input elements into a
313 * {@code String}, in encounter order
314 */
315 public static Collector<CharSequence, ?, String> joining() {
316 return new CollectorImpl<CharSequence, StringBuilder, String>(
317 StringBuilder::new, StringBuilder::append,
318 (r1, r2) -> { r1.append(r2); return r1; },
319 StringBuilder::toString, CH_NOID);
320 }
321
322 /**
323 * Returns a {@code Collector} that concatenates the input elements,
324 * separated by the specified delimiter, in encounter order.
325 *
326 * @param delimiter the delimiter to be used between each element
327 * @return A {@code Collector} which concatenates CharSequence elements,
328 * separated by the specified delimiter, in encounter order
1394 * @param keyMapper a mapping function to produce keys
1395 * @param valueMapper a mapping function to produce values
1396 * @return a {@code Collector} which collects elements into a {@code Map}
1397 * whose keys and values are the result of applying mapping functions to
1398 * the input elements
1399 *
1400 * @see #toMap(Function, Function, BinaryOperator)
1401 * @see #toMap(Function, Function, BinaryOperator, Supplier)
1402 * @see #toConcurrentMap(Function, Function)
1403 */
1404 public static <T, K, U>
1405 Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
1406 Function<? super T, ? extends U> valueMapper) {
1407 return new CollectorImpl<>(HashMap::new,
1408 uniqKeysMapAccumulator(keyMapper, valueMapper),
1409 uniqKeysMapMerger(),
1410 CH_ID);
1411 }
1412
1413 /**
1414 * Returns a {@code Collector} that accumulates elements into a
1415 * {@code Map} whose keys and values are the result of applying the provided
1416 * mapping functions to the input elements.
1417 *
1418 * <p>If the mapped
1419 * keys contain duplicates (according to {@link Object#equals(Object)}),
1420 * the value mapping function is applied to each equal element, and the
1421 * results are merged using the provided merging function.
1422 *
1423 * <p>There are no guarantees on the type, mutability, serializability,
1424 * or thread-safety of the {@code Map} returned.
1425 *
1426 * @apiNote
1427 * There are multiple ways to deal with collisions between multiple elements
1428 * mapping to the same key. The other forms of {@code toMap} simply use
1429 * a merge function that throws unconditionally, but you can easily write
1430 * more flexible merge policies. For example, if you have a stream
1431 * of {@code Person}, and you want to produce a "phone book" mapping name to
1432 * address, but it is possible that two persons have the same name, you can
1433 * do as follows to gracefully deal with these collisions, and produce a
1456 * @param mergeFunction a merge function, used to resolve collisions between
1457 * values associated with the same key, as supplied
1458 * to {@link Map#merge(Object, Object, BiFunction)}
1459 * @return a {@code Collector} which collects elements into a {@code Map}
1460 * whose keys are the result of applying a key mapping function to the input
1461 * elements, and whose values are the result of applying a value mapping
1462 * function to all input elements equal to the key and combining them
1463 * using the merge function
1464 *
1465 * @see #toMap(Function, Function)
1466 * @see #toMap(Function, Function, BinaryOperator, Supplier)
1467 * @see #toConcurrentMap(Function, Function, BinaryOperator)
1468 */
1469 public static <T, K, U>
1470 Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
1471 Function<? super T, ? extends U> valueMapper,
1472 BinaryOperator<U> mergeFunction) {
1473 return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
1474 }
1475
1476 /**
1477 * Returns a {@code Collector} that accumulates elements into a
1478 * {@code Map} whose keys and values are the result of applying the provided
1479 * mapping functions to the input elements.
1480 *
1481 * <p>If the mapped
1482 * keys contain duplicates (according to {@link Object#equals(Object)}),
1483 * the value mapping function is applied to each equal element, and the
1484 * results are merged using the provided merging function. The {@code Map}
1485 * is created by a provided supplier function.
1486 *
1487 * @implNote
1488 * The returned {@code Collector} is not concurrent. For parallel stream
1489 * pipelines, the {@code combiner} function operates by merging the keys
1490 * from one map into another, which can be an expensive operation. If it is
1491 * not required that results are merged into the {@code Map} in encounter
1492 * order, using {@link #toConcurrentMap(Function, Function, BinaryOperator, Supplier)}
1493 * may offer better parallel performance.
1494 *
1495 * @param <T> the type of the input elements
|
99 *
100 * }</pre>
101 *
102 * @since 1.8
103 */
104 public final class Collectors {
105
106 static final Set<Collector.Characteristics> CH_CONCURRENT_ID
107 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
108 Collector.Characteristics.UNORDERED,
109 Collector.Characteristics.IDENTITY_FINISH));
110 static final Set<Collector.Characteristics> CH_CONCURRENT_NOID
111 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.CONCURRENT,
112 Collector.Characteristics.UNORDERED));
113 static final Set<Collector.Characteristics> CH_ID
114 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
115 static final Set<Collector.Characteristics> CH_UNORDERED_ID
116 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED,
117 Collector.Characteristics.IDENTITY_FINISH));
118 static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
119 static final Set<Collector.Characteristics> CH_UNORDERED_NOID
120 = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.UNORDERED));
121
122 private Collectors() { }
123
124 /**
125 * Construct an {@code IllegalStateException} with appropriate message.
126 *
127 * @param k the duplicate key
128 * @param u 1st value to be accumulated/merged
129 * @param v 2nd value to be accumulated/merged
130 */
131 private static IllegalStateException duplicateKeyException(
132 Object k, Object u, Object v) {
133 return new IllegalStateException(String.format(
134 "Duplicate key %s (attempted merging values %s and %s)",
135 k, u, v));
136 }
137
138 /**
139 * {@code BinaryOperator<Map>} that merges the contents of its right
140 * argument into its left argument, throwing {@code IllegalStateException}
264 }
265
266 /**
267 * Returns a {@code Collector} that accumulates the input elements into a
268 * new {@code List}. There are no guarantees on the type, mutability,
269 * serializability, or thread-safety of the {@code List} returned; if more
270 * control over the returned {@code List} is required, use {@link #toCollection(Supplier)}.
271 *
272 * @param <T> the type of the input elements
273 * @return a {@code Collector} which collects all the input elements into a
274 * {@code List}, in encounter order
275 */
276 public static <T>
277 Collector<T, ?, List<T>> toList() {
278 return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
279 (left, right) -> { left.addAll(right); return left; },
280 CH_ID);
281 }
282
283 /**
284 * Returns a {@code Collector} that accumulates the input elements into an
285 * <a href="List.html#unmodifiable">unmodifiable</a> {@code List}.
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 * @since 10
291 */
292 @SuppressWarnings("unchecked")
293 public static <T>
294 Collector<T, ?, List<T>> toUnmodifiableList() {
295 return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
296 (left, right) -> { left.addAll(right); return left; },
297 list -> (List<T>)List.of(list.toArray()),
298 CH_NOID);
299 }
300
301 /**
302 * Returns a {@code Collector} that accumulates the input elements into a
303 * new {@code Set}. There are no guarantees on the type, mutability,
304 * serializability, or thread-safety of the {@code Set} returned; if more
305 * control over the returned {@code Set} is required, use
306 * {@link #toCollection(Supplier)}.
307 *
308 * <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
309 * Collector.
310 *
311 * @param <T> the type of the input elements
312 * @return a {@code Collector} which collects all the input elements into a
313 * {@code Set}
314 */
315 public static <T>
316 Collector<T, ?, Set<T>> toSet() {
317 return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
318 (left, right) -> {
319 if (left.size() < right.size()) {
320 right.addAll(left); return right;
321 } else {
322 left.addAll(right); return left;
323 }
324 },
325 CH_UNORDERED_ID);
326 }
327
328 /**
329 * Returns a {@code Collector} that accumulates the input elements into an
330 * <a href="Set.html#unmodifiable">unmodifiable</a> {@code Set}.
331 *
332 * <p>This is an {@link Collector.Characteristics#UNORDERED unordered}
333 * Collector.
334 *
335 * @param <T> the type of the input elements
336 * @return a {@code Collector} which collects all the input elements into a
337 * {@code Set}
338 * @since 10
339 */
340 @SuppressWarnings("unchecked")
341 public static <T>
342 Collector<T, ?, Set<T>> toUnmodifiableSet() {
343 return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
344 (left, right) -> {
345 if (left.size() < right.size()) {
346 right.addAll(left); return right;
347 } else {
348 left.addAll(right); return left;
349 }
350 },
351 set -> (Set<T>)Set.of(set.toArray()),
352 CH_UNORDERED_NOID);
353 }
354
355 /**
356 * Returns a {@code Collector} that concatenates the input elements into a
357 * {@code String}, in encounter order.
358 *
359 * @return a {@code Collector} that concatenates the input elements into a
360 * {@code String}, in encounter order
361 */
362 public static Collector<CharSequence, ?, String> joining() {
363 return new CollectorImpl<CharSequence, StringBuilder, String>(
364 StringBuilder::new, StringBuilder::append,
365 (r1, r2) -> { r1.append(r2); return r1; },
366 StringBuilder::toString, CH_NOID);
367 }
368
369 /**
370 * Returns a {@code Collector} that concatenates the input elements,
371 * separated by the specified delimiter, in encounter order.
372 *
373 * @param delimiter the delimiter to be used between each element
374 * @return A {@code Collector} which concatenates CharSequence elements,
375 * separated by the specified delimiter, in encounter order
1441 * @param keyMapper a mapping function to produce keys
1442 * @param valueMapper a mapping function to produce values
1443 * @return a {@code Collector} which collects elements into a {@code Map}
1444 * whose keys and values are the result of applying mapping functions to
1445 * the input elements
1446 *
1447 * @see #toMap(Function, Function, BinaryOperator)
1448 * @see #toMap(Function, Function, BinaryOperator, Supplier)
1449 * @see #toConcurrentMap(Function, Function)
1450 */
1451 public static <T, K, U>
1452 Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
1453 Function<? super T, ? extends U> valueMapper) {
1454 return new CollectorImpl<>(HashMap::new,
1455 uniqKeysMapAccumulator(keyMapper, valueMapper),
1456 uniqKeysMapMerger(),
1457 CH_ID);
1458 }
1459
1460 /**
1461 * Returns a {@code Collector} that accumulates the input elements into an
1462 * <a href="Map.html#unmodifiable">unmodifiable</a> {@code Map},
1463 * whose keys and values are the result of applying the provided
1464 * mapping functions to the input elements.
1465 *
1466 * <p>If the mapped keys contain duplicates (according to
1467 * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1468 * thrown when the collection operation is performed. If the mapped keys
1469 * may have duplicates, use {@link #toUnmodifiableMap(Function, Function, BinaryOperator)}
1470 * instead.
1471 *
1472 * @param <T> the type of the input elements
1473 * @param <K> the output type of the key mapping function
1474 * @param <U> the output type of the value mapping function
1475 * @param keyMapper a mapping function to produce keys
1476 * @param valueMapper a mapping function to produce values
1477 * @return a {@code Collector} which collects elements into an unmodifiable {@code Map}
1478 * whose keys and values are the result of applying mapping functions to
1479 * the input elements
1480 *
1481 * @see #toUnmodifiableMap(Function, Function, BinaryOperator)
1482 * @since 10
1483 */
1484 @SuppressWarnings({"rawtypes", "unchecked"})
1485 public static <T, K, U>
1486 Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
1487 Function<? super T, ? extends U> valueMapper) {
1488 return new CollectorImpl<>(() -> new ArrayList<Map.Entry<K, U>>(),
1489 (list, t) -> list.add(Map.entry(keyMapper.apply(t), valueMapper.apply(t))),
1490 (list1, list2) -> { list1.addAll(list2); return list1; },
1491 list -> (Map<K,U>)Map.ofEntries(list.toArray(new Map.Entry[0])),
1492 CH_UNORDERED_NOID);
1493 }
1494
1495 /**
1496 * Returns a {@code Collector} that accumulates elements into a
1497 * {@code Map} whose keys and values are the result of applying the provided
1498 * mapping functions to the input elements.
1499 *
1500 * <p>If the mapped
1501 * keys contain duplicates (according to {@link Object#equals(Object)}),
1502 * the value mapping function is applied to each equal element, and the
1503 * results are merged using the provided merging function.
1504 *
1505 * <p>There are no guarantees on the type, mutability, serializability,
1506 * or thread-safety of the {@code Map} returned.
1507 *
1508 * @apiNote
1509 * There are multiple ways to deal with collisions between multiple elements
1510 * mapping to the same key. The other forms of {@code toMap} simply use
1511 * a merge function that throws unconditionally, but you can easily write
1512 * more flexible merge policies. For example, if you have a stream
1513 * of {@code Person}, and you want to produce a "phone book" mapping name to
1514 * address, but it is possible that two persons have the same name, you can
1515 * do as follows to gracefully deal with these collisions, and produce a
1538 * @param mergeFunction a merge function, used to resolve collisions between
1539 * values associated with the same key, as supplied
1540 * to {@link Map#merge(Object, Object, BiFunction)}
1541 * @return a {@code Collector} which collects elements into a {@code Map}
1542 * whose keys are the result of applying a key mapping function to the input
1543 * elements, and whose values are the result of applying a value mapping
1544 * function to all input elements equal to the key and combining them
1545 * using the merge function
1546 *
1547 * @see #toMap(Function, Function)
1548 * @see #toMap(Function, Function, BinaryOperator, Supplier)
1549 * @see #toConcurrentMap(Function, Function, BinaryOperator)
1550 */
1551 public static <T, K, U>
1552 Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
1553 Function<? super T, ? extends U> valueMapper,
1554 BinaryOperator<U> mergeFunction) {
1555 return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
1556 }
1557
1558
1559 /**
1560 * Returns a {@code Collector} that accumulates the input elements into an
1561 * <a href="Map.html#unmodifiable">unmodifiable</a> {@code Map},
1562 * whose keys and values are the result of applying the provided
1563 * mapping functions to the input elements.
1564 *
1565 * <p>If the mapped
1566 * keys contain duplicates (according to {@link Object#equals(Object)}),
1567 * the value mapping function is applied to each equal element, and the
1568 * results are merged using the provided merging function.
1569 *
1570 * @param <T> the type of the input elements
1571 * @param <K> the output type of the key mapping function
1572 * @param <U> the output type of the value mapping function
1573 * @param keyMapper a mapping function to produce keys
1574 * @param valueMapper a mapping function to produce values
1575 * @param mergeFunction a merge function, used to resolve collisions between
1576 * values associated with the same key, as supplied
1577 * to {@link Map#merge(Object, Object, BiFunction)}
1578 * @return a {@code Collector} which collects elements into an unmodifiable {@code Map}
1579 * whose keys are the result of applying a key mapping function to the input
1580 * elements, and whose values are the result of applying a value mapping
1581 * function to all input elements equal to the key and combining them
1582 * using the merge function
1583 *
1584 * @see #toUnmodifiableMap(Function, Function)
1585 * @since 10
1586 */
1587 @SuppressWarnings({"rawtypes", "unchecked"})
1588 public static <T, K, U>
1589 Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
1590 Function<? super T, ? extends U> valueMapper,
1591 BinaryOperator<U> mergeFunction) {
1592 return collectingAndThen(
1593 toMap(keyMapper, valueMapper, mergeFunction, HashMap::new),
1594 hm -> (Map<K,U>)Map.ofEntries(hm.entrySet().toArray(new Map.Entry[0])));
1595 }
1596
1597 /**
1598 * Returns a {@code Collector} that accumulates elements into a
1599 * {@code Map} whose keys and values are the result of applying the provided
1600 * mapping functions to the input elements.
1601 *
1602 * <p>If the mapped
1603 * keys contain duplicates (according to {@link Object#equals(Object)}),
1604 * the value mapping function is applied to each equal element, and the
1605 * results are merged using the provided merging function. The {@code Map}
1606 * is created by a provided supplier function.
1607 *
1608 * @implNote
1609 * The returned {@code Collector} is not concurrent. For parallel stream
1610 * pipelines, the {@code combiner} function operates by merging the keys
1611 * from one map into another, which can be an expensive operation. If it is
1612 * not required that results are merged into the {@code Map} in encounter
1613 * order, using {@link #toConcurrentMap(Function, Function, BinaryOperator, Supplier)}
1614 * may offer better parallel performance.
1615 *
1616 * @param <T> the type of the input elements
|