当须要将一个List转换为Map时,能够应用 Java 8 中的 Collectors.toMap() 办法,Map是由key-value组成的键值对汇合,在应用Collectors.toMap() 办法时,如果值为空,会报空指针异样,上面通过一个实例来验证一下。

首先定义一个 Student.java

package com.magic.npe;public class Student {    private String name;    private Integer age;    public Student(String name, Integer age) {        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }}

再创立一个 Test.java 类,用来验证将 List<Student> 转换为 Map<String, Integer>。

package com.magic.npe;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.stream.Collectors;public class Test {    public static void main(String[] args) {        List<Student> students = new ArrayList<>();        students.add(new Student("张三", 18));        students.add(new Student("李四", 21));        students.add(new Student("王五", null));        Map<String, Integer> studentMap = students.stream().collect(Collectors.toMap(Student::getName, Student::getAge));        System.out.println(studentMap);    }}

运行程序,间接报出如下的错误信息

Exception in thread "main" java.lang.NullPointerException    at java.util.HashMap.merge(HashMap.java:1224)    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:1374)    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)    at com.magic.npe.Test.main(Test.java:16)

查看一下 Collectors.toMap() 办法的源码,如下:

public static <T, K, U>    Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,                                    Function<? super T, ? extends U> valueMapper,                                    BinaryOperator<U> mergeFunction) {    return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);}

默认会创立一个 HashMap,持续查看源码:

public static <T, K, U, M extends Map<K, U>>    Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,                             Function<? super T, ? extends U> valueMapper,                             BinaryOperator<U> mergeFunction,                             Supplier<M> mapSupplier) {    BiConsumer<M, T> accumulator        = (map, element) -> map.merge(keyMapper.apply(element),                                      valueMapper.apply(element), mergeFunction);    return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);}

通过 Map.merge() 办法来合并,源码如下:

default V merge(K key, V value,                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {    Objects.requireNonNull(remappingFunction);    Objects.requireNonNull(value);    V oldValue = get(key);    V newValue = (oldValue == null) ? value :    remappingFunction.apply(oldValue, value);    if(newValue == null) {        remove(key);    } else {        put(key, newValue);    }    return newValue;}

能够看到,在 merge() 办法中,要求 value 值不能为空

Objects.requireNonNull(value);

持续查看一下 Objects.requireNonNull() 办法的源码

public static <T> T requireNonNull(T obj) {    if (obj == null)        throw new NullPointerException();    return obj;}

如果值为空,则会间接报出 NullPointerException 异样。

那么,对于这个空指针异样问题,如何解决呢?个别有两种形式:

(1)替换空值null为一个默认值,比方0

package com.magic.npe;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.Optional;import java.util.stream.Collectors;public class Test {  public static void main(String[] args) {      List<Student> students = new ArrayList<>();      students.add(new Student("张三", 18));      students.add(new Student("李四", 21));      students.add(new Student("王五", null));      // 如果age为null,则间接赋值默认值0      Map<String, Integer> studentMap = students.stream().collect(Collectors.toMap(Student::getName, s -> Optional.ofNullable(s.getAge()).orElse(0)));      System.out.println(studentMap);  }}

运行程序,能够看到如下输入

{李四=21, 张三=18, 王五=0}

(2)调用 collect() 的其余实现办法

package com.magic.npe;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;public class Test {  public static void main(String[] args) {      List<Student> students = new ArrayList<>();      students.add(new Student("张三", 18));      students.add(new Student("李四", 21));      students.add(new Student("王五", null));      Map<String, Integer> studentMap = students.stream().collect(HashMap::new, (map, student) -> map.put(student.getName(), student.getAge()), HashMap::putAll);      System.out.println(studentMap);  }}

运行程序,能够看到如下输入

{李四=21, 张三=18, 王五=null}