Skip to content

Commit 45a42ef

Browse files
committed
Better error message for Collectors.toMap
1 parent 1e021cf commit 45a42ef

File tree

2 files changed

+50
-10
lines changed

2 files changed

+50
-10
lines changed

user/super/com/google/gwt/emul/java/util/stream/Collectors.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -376,12 +376,31 @@ public static <T> Collector<T,?,List<T>> toList() {
376376
public static <T, K, U> Collector<T, ?, Map<K, U>> toMap(
377377
final Function<? super T, ? extends K> keyMapper,
378378
final Function<? super T, ? extends U> valueMapper) {
379-
return toMap(
380-
keyMapper,
381-
valueMapper,
379+
return Collector.of(
380+
HashMap::new,
381+
(map, item) -> {
382+
K key = keyMapper.apply(item);
383+
U newValue = Objects.requireNonNull(valueMapper.apply(item));
384+
if (map.containsKey(key)) {
385+
throw getDuplicateKeyException(key);
386+
} else {
387+
map.put(key, newValue);
388+
}
389+
},
382390
(m1, m2) -> {
383-
throw new IllegalStateException("Duplicate key " + m1);
384-
});
391+
for (Map.Entry<K, U> entry : m2.entrySet()) {
392+
if (m1.get(entry.getKey()) != null) {
393+
throw getDuplicateKeyException(entry.getKey());
394+
}
395+
m1.put(entry.getKey(), entry.getValue());
396+
}
397+
return m1;
398+
},
399+
Collector.Characteristics.IDENTITY_FINISH);
400+
}
401+
402+
private static RuntimeException getDuplicateKeyException(Object key) {
403+
return new IllegalStateException("Duplicate key: " + key);
385404
}
386405

387406
public static <T, K, U> Collector<T, ?, Map<K, U>> toMap(
@@ -423,7 +442,7 @@ private static <T, R> Function<T, R> disallowNulls(Function<T, R> func) {
423442
mapSupplier,
424443
(map, item) -> {
425444
K key = keyMapper.apply(item);
426-
U newValue = valueMapper.apply(item);
445+
U newValue = Objects.requireNonNull(valueMapper.apply(item));
427446
if (map.containsKey(key)) {
428447
map.put(key, mergeFunction.apply(map.get(key), newValue));
429448
} else {

user/test/com/google/gwt/emultest/java8/util/stream/CollectorsTest.java

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import java.util.IntSummaryStatistics;
5050
import java.util.LinkedHashMap;
5151
import java.util.List;
52+
import java.util.Locale;
5253
import java.util.LongSummaryStatistics;
5354
import java.util.Map;
5455
import java.util.Optional;
@@ -406,12 +407,13 @@ public void testList() {
406407
}
407408

408409
public void testMap() {
409-
Collector<String, ?, Map<String, String>> c = toMap(Function.identity(), Function.identity());
410+
Function<String, String> toUpper = s -> s.toUpperCase(Locale.ROOT);
411+
Collector<String, ?, Map<String, String>> c = toMap(Function.identity(), toUpper);
410412

411413
// two distinct items
412414
Map<String, String> map = new HashMap<>();
413-
map.put("a", "a");
414-
map.put("b", "b");
415+
map.put("a", "A");
416+
map.put("b", "B");
415417
applyItems(map, c, "a", "b");
416418

417419
// inline applyItems and test each to confirm failure for duplicates
@@ -425,10 +427,11 @@ public void testMap() {
425427
applyItemsWithSplitting(c, "a", "a");
426428
fail("expected IllegalStateException");
427429
} catch (IllegalStateException expected) {
430+
assertEquals("Duplicate key a", expected.getMessage());
428431
}
429432

430433
assertZeroItemsCollectedAs(Collections.emptyMap(), c);
431-
assertSingleItemCollectedAs(Collections.singletonMap("a", "a"), c, "a");
434+
assertSingleItemCollectedAs(Collections.singletonMap("a", "A"), c, "a");
432435

433436
List<String> seen = new ArrayList<>();
434437
c = toMap(Function.identity(), Function.identity(), (s, s2) -> {
@@ -442,6 +445,24 @@ public void testMap() {
442445
assertEquals(Arrays.asList("first: a", "second: a", "first: a", "second: a"), seen);
443446
}
444447

448+
public void testMapInvalid() {
449+
Collector<String, ?, Map<String, String>> c = toMap(Function.identity(), ignore -> null);
450+
451+
// inline applyItems and test each to confirm failure for duplicates
452+
try {
453+
applyItemsWithoutSplitting(c, "a", "b");
454+
fail("expected NullPointerException");
455+
} catch (NullPointerException expected) {
456+
assertEquals("Duplicate key a", expected.getMessage());
457+
}
458+
try {
459+
applyItemsWithSplitting(c, "a", "a");
460+
fail("expected NullPointerException");
461+
} catch (NullPointerException expected) {
462+
assertEquals("Duplicate key a", expected.getMessage());
463+
}
464+
}
465+
445466
public void testSet() {
446467
Collector<String, ?, Set<String>> c = toSet();
447468

0 commit comments

Comments
 (0)