问题描述
如果其中一个值为null,则Java 8 Collectors.toMap
会抛出 NullPointerException
。我不明白这种行为,map可以包含null指针作为值而没有任何问题。 Collectors.toMap
?
The Java 8 Collectors.toMap
throws a NullPointerException
if one of the values is 'null'. I don't understand this behaviour, maps can contain null pointers as value without any problems. Is there a good reason why values cannot be null for Collectors.toMap
?
还有一个很好的理由为什么值不能为null解决这个问题的方法有哪些,或者我应该恢复原状for for循环?
Also, is there a nice Java 8 way of fixing this, or should I revert to plain old for loop?
我的问题的一个例子:
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:
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)
Java 11中仍存在此问题。
This problem still exists in Java 11.
推荐答案
使用收集器
的静态方法是不可能的。 解释 toMap
基于:
It is not possible with the static methods of Collectors
. The javadoc of toMap
explains that toMap
is based on Map.merge
:
以及说:
您可以使用列表方法。
You can avoid the for loop by using the forEach
method of your list.
Map<Integer, Boolean> answerMap = new HashMap<>();
answerList.forEach((answer) -> answerMap.put(answer.getId(), answer.getAnswer()));
但它并不比旧方式简单:
but it is not really simple than the old way:
Map<Integer, Boolean> answerMap = new HashMap<>();
for (Answer answer : answerList) {
answerMap.put(answer.getId(), answer.getAnswer());
}
这篇关于Collectors.toMap中的Java 8 NullPointerException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!