Java 8-> Collectors.toMap->重复键

时间:2019-08-01 14:36:32

标签: java-8 java-stream

我正在尝试将可用List的{​​{1}}转换为Currency,要基于货币数字代码进行查找,我想获取String代码。这是代码。

但是上面的这段代码抛出了错误,我对Java 8还是很陌生,所以我大吃一惊:

Map

但是上面的这段代码抛出了错误,我对Java 8还是很陌生,所以我大吃一惊

Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.IllegalStateException: Duplicate key YUM
    at java.util.stream.Collectors.lambda$throwingMerger$0(Collectors.java:133)
    at java.util.HashMap.merge(HashMap.java:1254)
    at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
    at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
    at java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1556)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

它应该以代码为键将所有货币加载到地图中。

1 个答案:

答案 0 :(得分:4)

Collectors.toMap()不接受重复的密钥。
由于您拥有Currency::getNumericCode的密钥,因此toMap()在遇到重复密钥时会引发此异常。

Caused by: java.lang.IllegalStateException: Duplicate key YUM

请注意,此处的错误消息具有误导性。键是Integer,而YUM不是。 YUM看起来像一个Currency实例,就是这样。
实际上,YUM指的是Currency处理的具有重复键的值(toMap())之一,而不是键值本身。这是Java bug fixed in Java 9

要解决您的问题,请使用Collectors.groupingBy()收集到Map<Integer, List<Currency>>,在这种情况下,您可以通过键获得多个值,或者将重复的键合并为toMap() ,例如保留最后一个条目:

private static final Map<Integer, Currency> NUMERIC_MAP = 
ISO_CURRENCY.stream()
            .collect(Collectors.toMap(Currency::getNumericCode, Function.identity(), (v1, v2)-> v2);

要回答您的评论,您可以通过以下方式找到罪魁祸首代码(重复项):

Map<Integer, List<Currency>> dupMap = 
ISO_CURRENCY.stream()
            .collect(Collectors.groupingBy(Currency::getNumericCode)
            .entrySet()
            .filter(e -> e.getValue().size() > 1)
            .collect(Collectors.toMap(Entry::getKey,Entry::getValue));

System.out.println(dupMap);