Java 8 Collectors.toMapzgłasza, NullPointerExceptionjeśli jedna z wartości ma wartość „null”. Nie rozumiem tego zachowania, mapy mogą zawierać zerowe wskaźniki jako wartość bez żadnych problemów. Czy istnieje dobry powód, dla którego wartości nie mogą mieć wartości null Collectors.toMap?
Czy jest też dobry sposób na naprawienie tego w Javie 8, czy powinienem powrócić do zwykłej starej pętli for?
Przykład mojego problemu:
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));
}
}
Ślad stosu:
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)
Ten problem nadal występuje w Javie 11.
nullmoże stanowić problem dla klucza, ale w tym przypadku jest to wartość.
null, HashMapna przykład może mieć jeden nullklucz i dowolną liczbę nullwartości, możesz spróbować utworzyć niestandardowy Collectorza pomocą HashMapzamiast zamiast domyślnego.
HashMap- jak pokazano w pierwszym wierszu stacktrace. Problemem nie jest to, że nie Mapmożna przechowywać nullwartości, ale że drugi argument Map#mergefunkcji nie może mieć wartości NULL.
nullzawsze było trochę problematyczne, jak w TreeMap. Może miły moment na wypróbowanieOptional<Boolean>? W przeciwnym razie podziel i użyj filtru.