4

UPDATE (after question marked as duplicate): Duplicate question/answer does not help me solve my issue, as the map I am getting is from external source.

I am trying to work something out using Java stream and collect features.

I have a map of Map<String, String[]> which I needs to convert to a Map<String, String> picking up the first element of the String array if it's not empty or putting null if it's null or empty

private Map<String, String> convertMyMap(Map<String, String[]> originalMap) {

        return originalMap.entrySet().stream().collect(
             Collectors.toMap(
                 e -> e.getKey(), 
                 e -> {
                          if (ArrayUtils.isNotEmpty(e.getValue()))
                               return e.getValue()[0];
                          return null;
                       }
             ));

I use below code to test it

Map<String, String[]> params =  new HashMap<String, String[]>();

params.put("test", new String[]{"1"});
params.put("test1", new String[]{"2", "1"});

//params.put("test2", new String[]{});   // THIS THROWS NPE
//params.put("test3", null);             // THIS THROWS NPE

convertMyMap(params).forEach((key, value) -> System.out.println(key + " "+ value));

As you can see when I try this with an empty array or null value for my original map, it throws NPE.

Exception in thread "main" java.lang.NullPointerException
    at java.util.HashMap.merge(Unknown Source)
    at java.util.stream.Collectors.lambda$toMap$172(Unknown Source)
    at java.util.stream.ReduceOps$3ReducingSink.accept(Unknown Source)
    at java.util.HashMap$EntrySpliterator.forEachRemaining(Unknown Source)
    at java.util.stream.AbstractPipeline.copyInto(Unknown Source)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
    at java.util.stream.AbstractPipeline.evaluate(Unknown Source)
    at java.util.stream.ReferencePipeline.collect(Unknown Source)

Any ideas what I am doing wrong here?

Abubakkar
  • 15,488
  • 8
  • 55
  • 83
  • 3
    Related: http://stackoverflow.com/questions/24630963/java-8-nullpointerexception-in-collectors-tomap – Djon May 19 '16 at 15:59
  • This explains the exception for `params.put("test3", null);`, but what about `params.put("test2", new String[]{});`? – Turing85 May 19 '16 at 16:01
  • @Turing85 If the array is empty, the mapped value is also null. The problem is not with how the original map is filled but how the one built with the collector is. – Alexis C. May 19 '16 at 16:04
  • 1
    @AlexisC. huh funny, true that. Haven't thought of this. Thanks for the explanation – Turing85 May 19 '16 at 16:05
  • You could use `params.put("test2", new String[]{null});` – GeekyDaddy May 19 '16 at 16:37
  • Duplicate question/answer does not help me solve my issue, as the map I am getting is from external source. – Abubakkar May 19 '16 at 17:59
  • @AbubakkarRangara Look at the second answer. – Alexis C. May 19 '16 at 18:23
  • @Abubakkar Rangara: you should read and try to understand the answers of the linked question. The Map is completely irrelevant. The second function passed to `toMap` is not allowed to return `null`. – Holger May 19 '16 at 18:54
  • Faster, simpler, working code is achieved without using streams. `private static Map convertMyMap(Map originalMap) { Map newMap = new HashMap<>(); for (Map.Entry e : originalMap.entrySet()) newMap.put(e.getKey(), ArrayUtils.isNotEmpty(e.getValue()) ? e.getValue()[0] : null); return newMap; }` – Boann May 19 '16 at 19:45
  • @Boann I already have that implementation, but wanted to try this with streams, collectors in Java 8 – Abubakkar May 19 '16 at 20:22

0 Answers0