Java8 Collectors.toMap 方法报空指针

Java8 Collectors.toMap 方法报空指针

薛定谔的汪

场景

开发中经常遇到将 List 集合转 map 的时候,Java8 的 Stream API 可以简化这一操作,减少代码:

1
2
3
List<Person> persons = ...
// 将 Person 的 id 作为 key, value 是 name, 当 key 重复时,取第一个(不加这个的话如果 key 重复会报错)
Map<Integer, String> idNameMap = persons.stream().collect(Collectors.toMap(Person::getId, Person::getName, (k1, k2) -> k1));

代码看着没问题,但是当某个 Person 的 name 是 null 时,会发生 NPE 异常:

1
2
3
4
5
6
7
8
9
10
java.lang.NullPointerException
at java.util.HashMap.merge(HashMap.java:1225)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
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)

这是因为 List 转 Map 时,使用的 HashMap 的 merge 方法,如果 Map 的 value 为 null,那么就会报 NPE,查看源码:

1
2
3
4
5
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction{
if (value == null)
throw new NullPointerException();
...
}

解决办法

遍历

1
2
Map<Integer, String> idNameMap = new HashMap<>();
persons.forEach(p -> idNameMap.put(p.getId(), p.getName()));

Stream重写了 collect 方法

1
Map<Integer, String> idNameMap = persons.stream().collect(HashMap::new, (map, p) -> map.put(p.getId(), p.getName()), HashMap::putAll);
  • Title: Java8 Collectors.toMap 方法报空指针
  • Author: 薛定谔的汪
  • Created at : 2019-03-30 18:01:54
  • Updated at : 2023-11-17 19:37:37
  • Link: https://www.zhengyk.cn/2019/03/30/java/CollectorstoMapNPE/
  • License: This work is licensed under CC BY-NC-SA 4.0.
On this page
Java8 Collectors.toMap 方法报空指针