Java 8 Collectors.toMap
zgłasza, NullPointerException
jeś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.
null
może stanowić problem dla klucza, ale w tym przypadku jest to wartość.
null
, HashMap
na przykład może mieć jeden null
klucz i dowolną liczbę null
wartości, możesz spróbować utworzyć niestandardowy Collector
za pomocą HashMap
zamiast zamiast domyślnego.
HashMap
- jak pokazano w pierwszym wierszu stacktrace. Problemem nie jest to, że nie Map
można przechowywać null
wartości, ale że drugi argument Map#merge
funkcji nie może mieć wartości NULL.
null
zawsze było trochę problematyczne, jak w TreeMap. Może miły moment na wypróbowanieOptional<Boolean>
? W przeciwnym razie podziel i użyj filtru.