src/share/classes/java/util/stream/Collectors.java
Print this page
*** 118,138 ****
static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
private Collectors() { }
/**
! * Returns a merge function, suitable for use in
! * {@link Map#merge(Object, Object, BiFunction) Map.merge()} or
! * {@link #toMap(Function, Function, BinaryOperator) toMap()}, which always
! * throws {@code IllegalStateException}. This can be used to enforce the
! * assumption that the elements being collected are distinct.
*
! * @param <T> the type of input arguments to the merge function
! * @return a merge function which always throw {@code IllegalStateException}
*/
! private static <T> BinaryOperator<T> throwingMerger() {
! return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
}
@SuppressWarnings("unchecked")
private static <I, R> Function<I, R> castingIdentity() {
return i -> (R) i;
--- 118,185 ----
static final Set<Collector.Characteristics> CH_NOID = Collections.emptySet();
private Collectors() { }
/**
! * Construct an {@code IllegalStateException} with appropriate message.
*
! * @param k the duplicate key
! * @param u 1st value to be accumulated/merged
! * @param v 2nd value to be accumulated/merged
! */
! private static IllegalStateException duplicateKeyException(
! Object k, Object u, Object v) {
! return new IllegalStateException(String.format(
! "Duplicate key %s (attempted merging values %s and %s)",
! k, u, v));
! }
!
! /**
! * {@code BinaryOperator<Map>} that merges the contents of its right
! * argument into its left argument, throwing {@code IllegalStateException}
! * if duplicate keys are encountered.
! *
! * @param <K> type of the map keys
! * @param <V> type of the map values
! * @param <M> type of the map
! * {@link Map#merge(Object, Object, BiFunction) Map.merge()}
! * @return a merge function for two maps
*/
! private static <K, V, M extends Map<K,V>>
! BinaryOperator<M> uniqKeysMapMerger() {
! return (m1, m2) -> {
! for (Map.Entry<K,V> e : m2.entrySet()) {
! K k = e.getKey();
! V v = Objects.requireNonNull(e.getValue());
! V u = m1.putIfAbsent(k, v);
! if (u != null) throw duplicateKeyException(k, u, v);
! }
! return m1;
! };
! }
!
! /**
! * {@code BiConsumer<Map, T>} that accumulates (key, value) pairs
! * extracted from elements into the map, throwing {@code IllegalStateException}
! * if duplicate keys are encountered.
! *
! * @param keyMapper a function that maps an element into a key
! * @param valueMapper a function that maps an element into a value
! * @param <T> type of elements
! * @param <K> type of map keys
! * @param <V> type of map values
! * @return an accumulating consumer
! */
! private static <T, K, V>
! BiConsumer<Map<K, V>, T> uniqKeysMapAccumulator(Function<? super T, ? extends K> keyMapper,
! Function<? super T, ? extends V> valueMapper) {
! return (map, element) -> {
! K k = keyMapper.apply(element);
! V v = Objects.requireNonNull(valueMapper.apply(element));
! V u = map.putIfAbsent(k, v);
! if (u != null) throw duplicateKeyException(k, u, v);
! };
}
@SuppressWarnings("unchecked")
private static <I, R> Function<I, R> castingIdentity() {
return i -> (R) i;
*** 1207,1217 ****
* @see #toConcurrentMap(Function, Function)
*/
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
! return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
/**
* Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided
--- 1254,1267 ----
* @see #toConcurrentMap(Function, Function)
*/
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
! return new CollectorImpl<>(HashMap::new,
! uniqKeysMapAccumulator(keyMapper, valueMapper),
! uniqKeysMapMerger(),
! CH_ID);
}
/**
* Returns a {@code Collector} that accumulates elements into a
* {@code Map} whose keys and values are the result of applying the provided
*** 1370,1380 ****
* @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
*/
public static <T, K, U>
Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
! return toConcurrentMap(keyMapper, valueMapper, throwingMerger(), ConcurrentHashMap::new);
}
/**
* Returns a concurrent {@code Collector} that accumulates elements into a
* {@code ConcurrentMap} whose keys and values are the result of applying
--- 1420,1433 ----
* @see #toConcurrentMap(Function, Function, BinaryOperator, Supplier)
*/
public static <T, K, U>
Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
! return new CollectorImpl<>(ConcurrentHashMap::new,
! uniqKeysMapAccumulator(keyMapper, valueMapper),
! uniqKeysMapMerger(),
! CH_CONCURRENT_ID);
}
/**
* Returns a concurrent {@code Collector} that accumulates elements into a
* {@code ConcurrentMap} whose keys and values are the result of applying