Search code examples
javajava-8hashmapjava-stream

Collectors.toMap() giving NPE Internally


I am trying to collect data as map in stream execution.

To make sure I am not having any duplicates I am using merger function but ending up having NPE.

See code snippet

streamableList().stream()
    .filter(Objects::nonNull)
    .filter(it-> nonNull(it.getKeyHere()))
    .collect(toMap(it -> it.getKeyHere(),
            it -> it.getValueHere(), (a1, a2) -> a1));

See exception below

java.lang.NullPointerException: null
        at java.util.HashMap.merge(HashMap.java:1216)
        at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
        at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
        at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
        at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
        at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
        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)....
.....and further calls of written code....

Can anyone suggest why it is failing while collecting and how to resolve?


Solution

  • HashMap::merge throws if any value is null.

    @Override
    public V merge(K key, V value,
                   BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        if (value == null)
            throw new NullPointerException(); //here
    

    So getValueHere must return null. You only do a null check against the item and the key, never the value.

    You can add another filter, or make sure your class doesn't contain null values.

    .filter(it -> Objects.nonNull(it.getValueHere()))