Java 8 Collectors.toMap
arroja un NullPointerException
si uno de los valores es 'nulo'. No entiendo este comportamiento, los mapas pueden contener punteros nulos como valor sin ningún problema. ¿Hay una buena razón por la cual los valores no pueden ser nulos Collectors.toMap
?
Además, ¿hay una buena forma de Java 8 para solucionar esto, o debería volver al ciclo anterior para el bucle?
Un ejemplo de mi problema:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
class Answer {
private int id;
private Boolean answer;
Answer() {
}
Answer(int id, Boolean answer) {
this.id = id;
this.answer = answer;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Boolean getAnswer() {
return answer;
}
public void setAnswer(Boolean answer) {
this.answer = answer;
}
}
public class Main {
public static void main(String[] args) {
List<Answer> answerList = new ArrayList<>();
answerList.add(new Answer(1, true));
answerList.add(new Answer(2, true));
answerList.add(new Answer(3, null));
Map<Integer, Boolean> answerMap =
answerList
.stream()
.collect(Collectors.toMap(Answer::getId, Answer::getAnswer));
}
}
Stacktrace:
Exception in thread "main" java.lang.NullPointerException
at java.util.HashMap.merge(HashMap.java:1216)
at java.util.stream.Collectors.lambda$toMap$168(Collectors.java:1320)
at java.util.stream.Collectors$$Lambda$5/1528902577.accept(Unknown Source)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1359)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
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)
at Main.main(Main.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Este problema todavía existe en Java 11.
null
podría ser un problema para una clave, pero en este caso es el valor.
null
, HashMap
por ejemplo, pueden tener una null
clave y cualquier número de null
valores, puede intentar crear una personalizada Collector
utilizando una en HashMap
lugar de utilizar la predeterminada.
HashMap
, como se muestra en la primera línea de stacktrace. El problema no es que un valor Map
no puede contener null
, sino que el segundo argumento de la Map#merge
función no puede ser nulo.
null
siempre fue un poco problemático, como en TreeMap. Tal vez un buen momento para probarOptional<Boolean>
? De lo contrario, divida y use el filtro.