亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java 8中Collectors.toMap空指針異常源碼解析

 更新時間:2023年08月10日 11:55:38   作者:十方  
這篇文章主要為大家介紹了Java 8中Collectors.toMap空指針異常源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

當需要將一個List轉(zhuǎn)換為Map時,可以使用 Java 8 中的 Collectors.toMap() 方法,Map是由key-value組成的鍵值對集合,在使用Collectors.toMap() 方法時,如果值為空,會報空指針異常,下面通過一個實例來驗證一下。

Student.java 類

首先定義一個 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 類創(chuàng)建

再創(chuàng)建一個 Test.java 類,用來驗證將 List<Student> 轉(zhuǎn)換為 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()

查看一下 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);
}

默認會創(chuàng)建一個 HashMap,繼續(xù)查看源碼:

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);

繼續(xù)查看一下 Objects.requireNonNull() 方法的源碼

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

NullPointerException 異常

如果值為空,則會直接報出 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)調(diào)用 collect() 的其他實現(xiàn)方法

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}

以上就是Java 8中Collectors.toMap空指針異常源碼解析的詳細內(nèi)容,更多關(guān)于Java8 Collectors.toMap空指針異常的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java 線程池框架

    Java 線程池框架

    本文主要介紹了Java 線程池框架的相關(guān)知識。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • java實現(xiàn)日期拆分的方法

    java實現(xiàn)日期拆分的方法

    這篇文章主要介紹了java實現(xiàn)日期拆分的方法,基于java日期類實現(xiàn)對日期字符串的拆分功能,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-07-07
  • java冒泡排序簡單實例

    java冒泡排序簡單實例

    本文主要介紹了JSONjava冒泡排序?qū)嵗c思路分析。具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • Spring通過<import>標簽導入外部配置文件

    Spring通過<import>標簽導入外部配置文件

    之前文章里我們講到Spring加載Xml配置文件的細節(jié),那么加載完了我們肯定要解析這個配置文件中定義的元素。這篇我們首先來分析下Spring是如何通過標簽導入外部配置文件的。
    2021-06-06
  • 通過代碼示例了解submit與execute的區(qū)別

    通過代碼示例了解submit與execute的區(qū)別

    這篇文章主要介紹了通過代碼示例了解submit與execute的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-09-09
  • 淺析SpringBoot統(tǒng)一返回結(jié)果的實現(xiàn)

    淺析SpringBoot統(tǒng)一返回結(jié)果的實現(xiàn)

    前后端開發(fā)過程中數(shù)據(jù)交互規(guī)范化是一件非常重要的事情,不僅可以減少前后端交互過程中出現(xiàn)的問題,也讓代碼邏輯更加具有條理,下面小編就和大家講講SpringBoot如何統(tǒng)一返回結(jié)果的吧
    2023-07-07
  • Java中Stream流對多個字段進行排序的方法

    Java中Stream流對多個字段進行排序的方法

    我們在處理數(shù)據(jù)的時候經(jīng)常會需要進行排序后再返回給前端調(diào)用,比如按照時間升序排序,前端展示數(shù)據(jù)就是按時間先后進行排序,下面這篇文章主要給大家介紹了關(guān)于Java中Stream流對多個字段進行排序的相關(guān)資料,需要的朋友可以參考下
    2023-10-10
  • Java基于阻塞隊列實現(xiàn)生產(chǎn)者消費者模型示例詳解

    Java基于阻塞隊列實現(xiàn)生產(chǎn)者消費者模型示例詳解

    這篇文章主要介紹了Java基于阻塞隊列實現(xiàn)生產(chǎn)者消費者模型,阻塞隊列的特點就是阻塞兩個字,阻塞功能使得生產(chǎn)者和消費者兩端的能力得以平衡,當有任何一端速度過快時,阻塞隊列便會把過快的速度降下來,感興趣的朋友可以參考下
    2023-12-12
  • 關(guān)于Spring Bean實例過程中使用反射和遞歸處理的Bean屬性填充問題

    關(guān)于Spring Bean實例過程中使用反射和遞歸處理的Bean屬性填充問題

    本文帶領(lǐng)大家一起學習下在Spring Bean實例過程中如何使用反射和遞歸處理的Bean屬性填充,需要在類 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加補全屬性方法,具體操作方法跟隨小編一起學習下吧
    2021-06-06
  • Java日期時間以及日期相互轉(zhuǎn)換

    Java日期時間以及日期相互轉(zhuǎn)換

    這篇文章主要為大家詳細介紹了Java日期時間,以及日期相互轉(zhuǎn)換的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10

最新評論