When running the following code compiled on JDK 8 the exception thrown is
java.lang.IllegalStateException: Duplicate key 1
which indicates that even though the new key is supposed to be a different object from a different type, the exception still mentions the original object.
List<Integer> ints = ImmutableList.of(1, 1);
Map<String, Integer> m = ints.stream()
.collect(Collectors.toMap(intgr -> String.valueOf(intgr + 1), Function.identity()));
The mapping function can be arbitrarily complex and totally different objects end up being mapped to the same key, why would this exception behavior be chosen?
I mean why the exception thrown is not "Duplicate key 2"?
Note: in our case the original value that was mapped is a third party class without toString
implementation so it was impossible to know what caused the duplication.
This could be a jdk bug. I think it may be resolved in higher version. (I'm using 1.8_162)
You can see Collectors#throwingMerger
.
private static <T> BinaryOperator<T> throwingMerger() {
return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
}
While the input parameter u, v
is come from Map#merge
. It is the old value and new value. So it is 1, 1
in your case. But the error message is Duplicate key
, it's totally wrong because both u
and v
is not key but value.
EDIT
Checked jdk 10, this bug has been fixed.
Now Collectors.toMap
use its own accumulate function rather than use Map.merge
.