src/java.base/share/classes/java/util/stream/Collectors.java

Print this page




 973             return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
 974         }
 975     }
 976 
 977     /**
 978      * Returns a concurrent {@code Collector} implementing a "group by"
 979      * operation on input elements of type {@code T}, grouping elements
 980      * according to a classification function.
 981      *
 982      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
 983      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
 984      *
 985      * <p>The classification function maps elements to some key type {@code K}.
 986      * The collector produces a {@code ConcurrentMap<K, List<T>>} whose keys are the
 987      * values resulting from applying the classification function to the input
 988      * elements, and whose corresponding values are {@code List}s containing the
 989      * input elements which map to the associated key under the classification
 990      * function.
 991      *
 992      * <p>There are no guarantees on the type, mutability, or serializability
 993      * of the {@code Map} or {@code List} objects returned, or of the
 994      * thread-safety of the {@code List} objects returned.
 995      * @implSpec
 996      * This produces a result similar to:
 997      * <pre>{@code
 998      *     groupingByConcurrent(classifier, toList());
 999      * }</pre>
1000      *
1001      * @param <T> the type of the input elements
1002      * @param <K> the type of the keys
1003      * @param classifier a classifier function mapping input elements to keys
1004      * @return a concurrent, unordered {@code Collector} implementing the group-by operation
1005      *
1006      * @see #groupingBy(Function)
1007      * @see #groupingByConcurrent(Function, Collector)
1008      * @see #groupingByConcurrent(Function, Supplier, Collector)
1009      */
1010     public static <T, K>
1011     Collector<T, ?, ConcurrentMap<K, List<T>>>
1012     groupingByConcurrent(Function<? super T, ? extends K> classifier) {
1013         return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
1014     }
1015 
1016     /**
1017      * Returns a concurrent {@code Collector} implementing a cascaded "group by"
1018      * operation on input elements of type {@code T}, grouping elements
1019      * according to a classification function, and then performing a reduction
1020      * operation on the values associated with a given key using the specified
1021      * downstream {@code Collector}.
1022      *
1023      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1024      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1025      *
1026      * <p>The classification function maps elements to some key type {@code K}.
1027      * The downstream collector operates on elements of type {@code T} and
1028      * produces a result of type {@code D}. The resulting collector produces a
1029      * {@code Map<K, D>}.
1030      *



1031      * <p>For example, to compute the set of last names of people in each city,
1032      * where the city names are sorted:
1033      * <pre>{@code
1034      *     ConcurrentMap<City, Set<String>> namesByCity
1035      *         = people.stream().collect(groupingByConcurrent(Person::getCity,
1036      *                                                        mapping(Person::getLastName, toSet())));
1037      * }</pre>
1038      *
1039      * @param <T> the type of the input elements
1040      * @param <K> the type of the keys
1041      * @param <A> the intermediate accumulation type of the downstream collector
1042      * @param <D> the result type of the downstream reduction
1043      * @param classifier a classifier function mapping input elements to keys
1044      * @param downstream a {@code Collector} implementing the downstream reduction
1045      * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
1046      *
1047      * @see #groupingBy(Function, Collector)
1048      * @see #groupingByConcurrent(Function)
1049      * @see #groupingByConcurrent(Function, Supplier, Collector)
1050      */


1126         }
1127         else {
1128             @SuppressWarnings("unchecked")
1129             Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
1130             Function<ConcurrentMap<K, A>, M> finisher = intermediate -> {
1131                 intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
1132                 @SuppressWarnings("unchecked")
1133                 M castResult = (M) intermediate;
1134                 return castResult;
1135             };
1136             return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID);
1137         }
1138     }
1139 
1140     /**
1141      * Returns a {@code Collector} which partitions the input elements according
1142      * to a {@code Predicate}, and organizes them into a
1143      * {@code Map<Boolean, List<T>>}.
1144      *
1145      * There are no guarantees on the type, mutability,
1146      * serializability, or thread-safety of the {@code Map} returned.

1147      *
1148      * @param <T> the type of the input elements
1149      * @param predicate a predicate used for classifying input elements
1150      * @return a {@code Collector} implementing the partitioning operation
1151      *
1152      * @see #partitioningBy(Predicate, Collector)
1153      */
1154     public static <T>
1155     Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
1156         return partitioningBy(predicate, toList());
1157     }
1158 
1159     /**
1160      * Returns a {@code Collector} which partitions the input elements according
1161      * to a {@code Predicate}, reduces the values in each partition according to
1162      * another {@code Collector}, and organizes them into a
1163      * {@code Map<Boolean, D>} whose values are the result of the downstream
1164      * reduction.
1165      *
1166      * <p>There are no guarantees on the type, mutability,


1195         }
1196         else {
1197             Function<Partition<A>, Map<Boolean, D>> finisher = par ->
1198                     new Partition<>(downstream.finisher().apply(par.forTrue),
1199                                     downstream.finisher().apply(par.forFalse));
1200             return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
1201         }
1202     }
1203 
1204     /**
1205      * Returns a {@code Collector} that accumulates elements into a
1206      * {@code Map} whose keys and values are the result of applying the provided
1207      * mapping functions to the input elements.
1208      *
1209      * <p>If the mapped keys contains duplicates (according to
1210      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1211      * thrown when the collection operation is performed.  If the mapped keys
1212      * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
1213      * instead.
1214      *



1215      * @apiNote
1216      * It is common for either the key or the value to be the input elements.
1217      * In this case, the utility method
1218      * {@link java.util.function.Function#identity()} may be helpful.
1219      * For example, the following produces a {@code Map} mapping
1220      * students to their grade point average:
1221      * <pre>{@code
1222      *     Map<Student, Double> studentToGPA
1223      *         students.stream().collect(toMap(Function.identity(),
1224      *                                         student -> computeGPA(student)));
1225      * }</pre>
1226      * And the following produces a {@code Map} mapping a unique identifier to
1227      * students:
1228      * <pre>{@code
1229      *     Map<String, Student> studentIdToStudent
1230      *         students.stream().collect(toMap(Student::getId,
1231      *                                         Function.identity());
1232      * }</pre>
1233      *
1234      * @implNote


1254      */
1255     public static <T, K, U>
1256     Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
1257                                     Function<? super T, ? extends U> valueMapper) {
1258         return new CollectorImpl<>(HashMap::new,
1259                                    uniqKeysMapAccumulator(keyMapper, valueMapper),
1260                                    uniqKeysMapMerger(),
1261                                    CH_ID);
1262     }
1263 
1264     /**
1265      * Returns a {@code Collector} that accumulates elements into a
1266      * {@code Map} whose keys and values are the result of applying the provided
1267      * mapping functions to the input elements.
1268      *
1269      * <p>If the mapped
1270      * keys contains duplicates (according to {@link Object#equals(Object)}),
1271      * the value mapping function is applied to each equal element, and the
1272      * results are merged using the provided merging function.
1273      *



1274      * @apiNote
1275      * There are multiple ways to deal with collisions between multiple elements
1276      * mapping to the same key.  The other forms of {@code toMap} simply use
1277      * a merge function that throws unconditionally, but you can easily write
1278      * more flexible merge policies.  For example, if you have a stream
1279      * of {@code Person}, and you want to produce a "phone book" mapping name to
1280      * address, but it is possible that two persons have the same name, you can
1281      * do as follows to gracefully deals with these collisions, and produce a
1282      * {@code Map} mapping names to a concatenated list of addresses:
1283      * <pre>{@code
1284      *     Map<String, String> phoneBook
1285      *         people.stream().collect(toMap(Person::getName,
1286      *                                       Person::getAddress,
1287      *                                       (s, a) -> s + ", " + a));
1288      * }</pre>
1289      *
1290      * @implNote
1291      * The returned {@code Collector} is not concurrent.  For parallel stream
1292      * pipelines, the {@code combiner} function operates by merging the keys
1293      * from one map into another, which can be an expensive operation.  If it is


1365                                 Function<? super T, ? extends U> valueMapper,
1366                                 BinaryOperator<U> mergeFunction,
1367                                 Supplier<M> mapSupplier) {
1368         BiConsumer<M, T> accumulator
1369                 = (map, element) -> map.merge(keyMapper.apply(element),
1370                                               valueMapper.apply(element), mergeFunction);
1371         return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
1372     }
1373 
1374     /**
1375      * Returns a concurrent {@code Collector} that accumulates elements into a
1376      * {@code ConcurrentMap} whose keys and values are the result of applying
1377      * the provided mapping functions to the input elements.
1378      *
1379      * <p>If the mapped keys contains duplicates (according to
1380      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1381      * thrown when the collection operation is performed.  If the mapped keys
1382      * may have duplicates, use
1383      * {@link #toConcurrentMap(Function, Function, BinaryOperator)} instead.
1384      *



1385      * @apiNote
1386      * It is common for either the key or the value to be the input elements.
1387      * In this case, the utility method
1388      * {@link java.util.function.Function#identity()} may be helpful.
1389      * For example, the following produces a {@code Map} mapping
1390      * students to their grade point average:
1391      * <pre>{@code
1392      *     Map<Student, Double> studentToGPA
1393      *         students.stream().collect(toMap(Function.identity(),
1394      *                                         student -> computeGPA(student)));
1395      * }</pre>
1396      * And the following produces a {@code Map} mapping a unique identifier to
1397      * students:
1398      * <pre>{@code
1399      *     Map<String, Student> studentIdToStudent
1400      *         students.stream().collect(toConcurrentMap(Student::getId,
1401      *                                                   Function.identity());
1402      * }</pre>
1403      *
1404      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and


1418      * @see #toConcurrentMap(Function, Function, BinaryOperator)
1419      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
1420      */
1421     public static <T, K, U>
1422     Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
1423                                                         Function<? super T, ? extends U> valueMapper) {
1424         return new CollectorImpl<>(ConcurrentHashMap::new,
1425                                    uniqKeysMapAccumulator(keyMapper, valueMapper),
1426                                    uniqKeysMapMerger(),
1427                                    CH_CONCURRENT_ID);
1428     }
1429 
1430     /**
1431      * Returns a concurrent {@code Collector} that accumulates elements into a
1432      * {@code ConcurrentMap} whose keys and values are the result of applying
1433      * the provided mapping functions to the input elements.
1434      *
1435      * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}),
1436      * the value mapping function is applied to each equal element, and the
1437      * results are merged using the provided merging function.



1438      *
1439      * @apiNote
1440      * There are multiple ways to deal with collisions between multiple elements
1441      * mapping to the same key.  The other forms of {@code toConcurrentMap} simply use
1442      * a merge function that throws unconditionally, but you can easily write
1443      * more flexible merge policies.  For example, if you have a stream
1444      * of {@code Person}, and you want to produce a "phone book" mapping name to
1445      * address, but it is possible that two persons have the same name, you can
1446      * do as follows to gracefully deals with these collisions, and produce a
1447      * {@code Map} mapping names to a concatenated list of addresses:
1448      * <pre>{@code
1449      *     Map<String, String> phoneBook
1450      *         people.stream().collect(toConcurrentMap(Person::getName,
1451      *                                                 Person::getAddress,
1452      *                                                 (s, a) -> s + ", " + a));
1453      * }</pre>
1454      *
1455      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1456      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1457      *




 973             return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
 974         }
 975     }
 976 
 977     /**
 978      * Returns a concurrent {@code Collector} implementing a "group by"
 979      * operation on input elements of type {@code T}, grouping elements
 980      * according to a classification function.
 981      *
 982      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
 983      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
 984      *
 985      * <p>The classification function maps elements to some key type {@code K}.
 986      * The collector produces a {@code ConcurrentMap<K, List<T>>} whose keys are the
 987      * values resulting from applying the classification function to the input
 988      * elements, and whose corresponding values are {@code List}s containing the
 989      * input elements which map to the associated key under the classification
 990      * function.
 991      *
 992      * <p>There are no guarantees on the type, mutability, or serializability
 993      * of the {@code ConcurrentMap} or {@code List} objects returned, or of the
 994      * thread-safety of the {@code List} objects returned.
 995      * @implSpec
 996      * This produces a result similar to:
 997      * <pre>{@code
 998      *     groupingByConcurrent(classifier, toList());
 999      * }</pre>
1000      *
1001      * @param <T> the type of the input elements
1002      * @param <K> the type of the keys
1003      * @param classifier a classifier function mapping input elements to keys
1004      * @return a concurrent, unordered {@code Collector} implementing the group-by operation
1005      *
1006      * @see #groupingBy(Function)
1007      * @see #groupingByConcurrent(Function, Collector)
1008      * @see #groupingByConcurrent(Function, Supplier, Collector)
1009      */
1010     public static <T, K>
1011     Collector<T, ?, ConcurrentMap<K, List<T>>>
1012     groupingByConcurrent(Function<? super T, ? extends K> classifier) {
1013         return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
1014     }
1015 
1016     /**
1017      * Returns a concurrent {@code Collector} implementing a cascaded "group by"
1018      * operation on input elements of type {@code T}, grouping elements
1019      * according to a classification function, and then performing a reduction
1020      * operation on the values associated with a given key using the specified
1021      * downstream {@code Collector}.
1022      *
1023      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1024      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1025      *
1026      * <p>The classification function maps elements to some key type {@code K}.
1027      * The downstream collector operates on elements of type {@code T} and
1028      * produces a result of type {@code D}. The resulting collector produces a
1029      * {@code Map<K, D>}.
1030      *
1031      * <p>There are no guarantees on the type, mutability, or serializability
1032      * of the {@code ConcurrentMap} returned.
1033      *
1034      * <p>For example, to compute the set of last names of people in each city,
1035      * where the city names are sorted:
1036      * <pre>{@code
1037      *     ConcurrentMap<City, Set<String>> namesByCity
1038      *         = people.stream().collect(groupingByConcurrent(Person::getCity,
1039      *                                                        mapping(Person::getLastName, toSet())));
1040      * }</pre>
1041      *
1042      * @param <T> the type of the input elements
1043      * @param <K> the type of the keys
1044      * @param <A> the intermediate accumulation type of the downstream collector
1045      * @param <D> the result type of the downstream reduction
1046      * @param classifier a classifier function mapping input elements to keys
1047      * @param downstream a {@code Collector} implementing the downstream reduction
1048      * @return a concurrent, unordered {@code Collector} implementing the cascaded group-by operation
1049      *
1050      * @see #groupingBy(Function, Collector)
1051      * @see #groupingByConcurrent(Function)
1052      * @see #groupingByConcurrent(Function, Supplier, Collector)
1053      */


1129         }
1130         else {
1131             @SuppressWarnings("unchecked")
1132             Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
1133             Function<ConcurrentMap<K, A>, M> finisher = intermediate -> {
1134                 intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
1135                 @SuppressWarnings("unchecked")
1136                 M castResult = (M) intermediate;
1137                 return castResult;
1138             };
1139             return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID);
1140         }
1141     }
1142 
1143     /**
1144      * Returns a {@code Collector} which partitions the input elements according
1145      * to a {@code Predicate}, and organizes them into a
1146      * {@code Map<Boolean, List<T>>}.
1147      *
1148      * There are no guarantees on the type, mutability,
1149      * serializability, or thread-safety of the {@code Map} or {@code List}
1150      * returned.
1151      *
1152      * @param <T> the type of the input elements
1153      * @param predicate a predicate used for classifying input elements
1154      * @return a {@code Collector} implementing the partitioning operation
1155      *
1156      * @see #partitioningBy(Predicate, Collector)
1157      */
1158     public static <T>
1159     Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
1160         return partitioningBy(predicate, toList());
1161     }
1162 
1163     /**
1164      * Returns a {@code Collector} which partitions the input elements according
1165      * to a {@code Predicate}, reduces the values in each partition according to
1166      * another {@code Collector}, and organizes them into a
1167      * {@code Map<Boolean, D>} whose values are the result of the downstream
1168      * reduction.
1169      *
1170      * <p>There are no guarantees on the type, mutability,


1199         }
1200         else {
1201             Function<Partition<A>, Map<Boolean, D>> finisher = par ->
1202                     new Partition<>(downstream.finisher().apply(par.forTrue),
1203                                     downstream.finisher().apply(par.forFalse));
1204             return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
1205         }
1206     }
1207 
1208     /**
1209      * Returns a {@code Collector} that accumulates elements into a
1210      * {@code Map} whose keys and values are the result of applying the provided
1211      * mapping functions to the input elements.
1212      *
1213      * <p>If the mapped keys contains duplicates (according to
1214      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1215      * thrown when the collection operation is performed.  If the mapped keys
1216      * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
1217      * instead.
1218      *
1219      * <p>There are no guarantees on the type, mutability, serializability,
1220      * or thread-safety of the {@code Map} returned.
1221      *
1222      * @apiNote
1223      * It is common for either the key or the value to be the input elements.
1224      * In this case, the utility method
1225      * {@link java.util.function.Function#identity()} may be helpful.
1226      * For example, the following produces a {@code Map} mapping
1227      * students to their grade point average:
1228      * <pre>{@code
1229      *     Map<Student, Double> studentToGPA
1230      *         students.stream().collect(toMap(Function.identity(),
1231      *                                         student -> computeGPA(student)));
1232      * }</pre>
1233      * And the following produces a {@code Map} mapping a unique identifier to
1234      * students:
1235      * <pre>{@code
1236      *     Map<String, Student> studentIdToStudent
1237      *         students.stream().collect(toMap(Student::getId,
1238      *                                         Function.identity());
1239      * }</pre>
1240      *
1241      * @implNote


1261      */
1262     public static <T, K, U>
1263     Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
1264                                     Function<? super T, ? extends U> valueMapper) {
1265         return new CollectorImpl<>(HashMap::new,
1266                                    uniqKeysMapAccumulator(keyMapper, valueMapper),
1267                                    uniqKeysMapMerger(),
1268                                    CH_ID);
1269     }
1270 
1271     /**
1272      * Returns a {@code Collector} that accumulates elements into a
1273      * {@code Map} whose keys and values are the result of applying the provided
1274      * mapping functions to the input elements.
1275      *
1276      * <p>If the mapped
1277      * keys contains duplicates (according to {@link Object#equals(Object)}),
1278      * the value mapping function is applied to each equal element, and the
1279      * results are merged using the provided merging function.
1280      *
1281      * <p>There are no guarantees on the type, mutability, serializability,
1282      * or thread-safety of the {@code Map} returned.
1283      *
1284      * @apiNote
1285      * There are multiple ways to deal with collisions between multiple elements
1286      * mapping to the same key.  The other forms of {@code toMap} simply use
1287      * a merge function that throws unconditionally, but you can easily write
1288      * more flexible merge policies.  For example, if you have a stream
1289      * of {@code Person}, and you want to produce a "phone book" mapping name to
1290      * address, but it is possible that two persons have the same name, you can
1291      * do as follows to gracefully deals with these collisions, and produce a
1292      * {@code Map} mapping names to a concatenated list of addresses:
1293      * <pre>{@code
1294      *     Map<String, String> phoneBook
1295      *         people.stream().collect(toMap(Person::getName,
1296      *                                       Person::getAddress,
1297      *                                       (s, a) -> s + ", " + a));
1298      * }</pre>
1299      *
1300      * @implNote
1301      * The returned {@code Collector} is not concurrent.  For parallel stream
1302      * pipelines, the {@code combiner} function operates by merging the keys
1303      * from one map into another, which can be an expensive operation.  If it is


1375                                 Function<? super T, ? extends U> valueMapper,
1376                                 BinaryOperator<U> mergeFunction,
1377                                 Supplier<M> mapSupplier) {
1378         BiConsumer<M, T> accumulator
1379                 = (map, element) -> map.merge(keyMapper.apply(element),
1380                                               valueMapper.apply(element), mergeFunction);
1381         return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
1382     }
1383 
1384     /**
1385      * Returns a concurrent {@code Collector} that accumulates elements into a
1386      * {@code ConcurrentMap} whose keys and values are the result of applying
1387      * the provided mapping functions to the input elements.
1388      *
1389      * <p>If the mapped keys contains duplicates (according to
1390      * {@link Object#equals(Object)}), an {@code IllegalStateException} is
1391      * thrown when the collection operation is performed.  If the mapped keys
1392      * may have duplicates, use
1393      * {@link #toConcurrentMap(Function, Function, BinaryOperator)} instead.
1394      *
1395      * <p>There are no guarantees on the type, mutability, or serializability
1396      * of the {@code ConcurrentMap} returned.
1397      *
1398      * @apiNote
1399      * It is common for either the key or the value to be the input elements.
1400      * In this case, the utility method
1401      * {@link java.util.function.Function#identity()} may be helpful.
1402      * For example, the following produces a {@code Map} mapping
1403      * students to their grade point average:
1404      * <pre>{@code
1405      *     Map<Student, Double> studentToGPA
1406      *         students.stream().collect(toMap(Function.identity(),
1407      *                                         student -> computeGPA(student)));
1408      * }</pre>
1409      * And the following produces a {@code Map} mapping a unique identifier to
1410      * students:
1411      * <pre>{@code
1412      *     Map<String, Student> studentIdToStudent
1413      *         students.stream().collect(toConcurrentMap(Student::getId,
1414      *                                                   Function.identity());
1415      * }</pre>
1416      *
1417      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and


1431      * @see #toConcurrentMap(Function, Function, BinaryOperator)
1432      * @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
1433      */
1434     public static <T, K, U>
1435     Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
1436                                                         Function<? super T, ? extends U> valueMapper) {
1437         return new CollectorImpl<>(ConcurrentHashMap::new,
1438                                    uniqKeysMapAccumulator(keyMapper, valueMapper),
1439                                    uniqKeysMapMerger(),
1440                                    CH_CONCURRENT_ID);
1441     }
1442 
1443     /**
1444      * Returns a concurrent {@code Collector} that accumulates elements into a
1445      * {@code ConcurrentMap} whose keys and values are the result of applying
1446      * the provided mapping functions to the input elements.
1447      *
1448      * <p>If the mapped keys contains duplicates (according to {@link Object#equals(Object)}),
1449      * the value mapping function is applied to each equal element, and the
1450      * results are merged using the provided merging function.
1451      *
1452      * <p>There are no guarantees on the type, mutability, or serializability
1453      * of the {@code ConcurrentMap} returned.
1454      *
1455      * @apiNote
1456      * There are multiple ways to deal with collisions between multiple elements
1457      * mapping to the same key.  The other forms of {@code toConcurrentMap} simply use
1458      * a merge function that throws unconditionally, but you can easily write
1459      * more flexible merge policies.  For example, if you have a stream
1460      * of {@code Person}, and you want to produce a "phone book" mapping name to
1461      * address, but it is possible that two persons have the same name, you can
1462      * do as follows to gracefully deals with these collisions, and produce a
1463      * {@code Map} mapping names to a concatenated list of addresses:
1464      * <pre>{@code
1465      *     Map<String, String> phoneBook
1466      *         people.stream().collect(toConcurrentMap(Person::getName,
1467      *                                                 Person::getAddress,
1468      *                                                 (s, a) -> s + ", " + a));
1469      * }</pre>
1470      *
1471      * <p>This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
1472      * {@link Collector.Characteristics#UNORDERED unordered} Collector.
1473      *