Reputation: 22041
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.
Upvotes: 5
Views: 2270
Reputation: 4496
This is because the merge function is called on values, and not on keys.
Excerpt from HashMap.merge
function (JDK 1.8.0_152):
v = remappingFunction.apply(old.value, value);
And the merge function in the Collector.toMap
is:
private static <T> BinaryOperator<T> throwingMerger() {
return (u,v) -> { throw new IllegalStateException(String.format("Duplicate key %s", u)); };
}
So I'd say it's a kind of inconsistency in the JDK. Instead of returning a message saying about "Duplicate key", the Collector
should return a message about "Duplicate value".
EDIT: Not even an inconsistency but a JDK bug fixed in JDK 9, as pointed out in Andy Turner's and Jai's comment.
Upvotes: 1
Reputation: 4691
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.
Checked jdk 10, this bug has been fixed.
Now Collectors.toMap
use its own accumulate function rather than use Map.merge
.
Upvotes: 5