Shankar
Shankar

Reputation: 175

Java 8 -> Collectors.toMap -> Duplicate key

I m trying to convert List of available Currency to a Map, To look up based on Currency Numeric code i want to get String code. Here is the code.

But this code above throwing below error, I m very new to Java 8 hence banging my head :

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)

But this code above throwing below error, I m very new to Java 8 hence banging my head

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());
  }
}

It should load all currencies into the map with code as keys.

Upvotes: 2

Views: 10897

Answers (1)

davidxxx
davidxxx

Reputation: 131496

Collectors.toMap() doesn't accept duplicates for keys.
Since you have that for Currency::getNumericCode, toMap() throws this exception when a duplicate key is encountered.

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

Note that here the error message is misleading. Keys are Integer while YUM is not. YUM looks like a Currency instance and that is.
Indeed, YUM refers to one of the values (Currency) processed by toMap() that have a duplicate key, not the key value itself. It is a Java bug fixed in Java 9.

To solve your issue, either use Collectors.groupingBy() to collect to a Map<Integer, List<Currency>> and in this case you could have multiple values by key or as alternative merge the duplicate keys with the toMap() overload, for example to keep the last entry :

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

To answer to your comment, you could find the culprit code (duplicates) in this way :

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);

Upvotes: 8

Related Questions