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

Sha*_*kar 0 java-8 java-stream

我正在尝试将Listavailable转换Currency为 a 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)
Run Code Online (Sandbox Code Playgroud)

但是上面的这段代码抛出了错误,我对 Java 8 很陌生,因此我很头疼

public class IsoCurrencyCode {

  private static final Set<Currency> ISO_CURRENCY = Currency.getAvailableCurrencies();

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

  public static void main(String[] args) {
    //
    Currency currency = NUMERIC_MAP.get(971);
    System.out.println(currency.getCurrencyCode());
  }
}
Run Code Online (Sandbox Code Playgroud)

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

dav*_*xxx 5

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

Caused by: java.lang.IllegalStateException: Duplicate key YUM
Run Code Online (Sandbox Code Playgroud)

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

要解决您的问题,请使用Collectors.groupingBy()to collect 到 a 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);
Run Code Online (Sandbox Code Playgroud)

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

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);
Run Code Online (Sandbox Code Playgroud)