为什么Collectors.toMap在重复键错误上报告值而不是键?
这真是一个关于细微问题的问题,但我的印象是在这里弄错了。 如果使用Collectors.toMap-method添加重复键,则会抛出带有“重复键”消息的exception。 为什么报告的价值而不是关键? 甚至两个? 这真是误导,不是吗?
这是一个certificate行为的小测试:
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class TestToMap { public static void main(String[] args) { List list = Arrays.asList( new Something("key1", "value1"), new Something("key2", "value2"), new Something("key3", "value3a"), new Something("key3", "value3b")); Map map = list.stream().collect(Collectors.toMap(o -> o.key, o -> o.value)); System.out.println(map); } private static class Something { final String key, value; Something(final String key, final String value){ this.key = key; this.value = value; } } }
这被报告为一个错误,请参阅JDK-8040892 ,并在Java 9中修复。阅读提交修复此问题 ,新的exception消息将是
String.format("Duplicate key %s (attempted merging values %s and %s)", k, u, v)
其中k
是重复键, u
和v
是映射到同一个键的两个冲突值。
正如其他答案已经陈述的那样,这是一个将在Java 9中修复的错误。错误产生的原因是, toMap
依赖于具有签名的Map.merge
V merge(K key, V value, BiFunction super V,? super V,? extends V> remappingFunction)
如果没有先前的key
映射,则此方法将插入key
– value
映射,否则,将评估remappingFunction以计算新值。 因此,如果不允许重复键,则可以直接提供一个无条件抛出exception的remappingFunction
,然后就完成了。 但是……如果你看一下函数签名,你会注意到这个函数只接收要合并的两个值 ,而不是键 。
当throwingMerger
为Java 8实现时,忽略了第一个参数不是关键,但更糟糕的是,修复它并不是直接的。
如果您尝试使用重载的toMap
收集器提供替代合并,您会注意到。 此时关键值不在范围内。 Java 9开发人员不得不为无重复的情况更改整个toMap
实现,以便能够提供报告受影响密钥的exception消息…
这是Jdk 8中的一个已知错误。抛出的消息应该显示至少两个存在键冲突的值,或者理想情况下显示发生冲突的键。 附件是相同的链接