当前位置: 首页 > 后端技术 > Java

Java 8中Collectors.toMap空指针异常源码分析

时间:2023-04-01 20:31:24 Java

Java8Collectors.toMap空指针异常源码分析使用Collectors.toMap()方法时,如果值为空,会报空指针异常。我们通过一个例子来验证一下。首先定义一个Student.java类包com.magic.npe;公共课学生{私人字符串名称;私人整数年龄;publicStudent(Stringname,Integerage){this.name=name;这个。年龄=年龄;}publicStringgetName(){返回名称;}publicvoidsetName(Stringname){this.name=name;}publicIntegergetAge(){返回年龄;}publicvoidsetAge(Integerage){this.age=age;}}创建另一个Test.java类来验证List到Map的转换。包com.magic.npe;导入java.util.ArrayList;导入java.util.List;导入java.util.Map;导入java.util.stream.Collectors;公共类测试{publicstaticvoidmain(String[]args){Liststudents=newArrayList<>();students.add(newStudent("张三",18));students.add(newStudent("李四",21));students.add(newStudent("王五",null));MapstudentMap=students.stream().collect(Collectors.toMap(Student::getName,Student::getAge));System.out.println(studentMap);}}运行程序,直接报告如下的错误信息Exceptioninthread"main"java.lang.NullPointerExceptionatjava.util.HashMap.merge(HashMap.java:1224)atjava.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)在java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)在java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)在java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)在java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)在java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)在java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)在java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)在com.magic.npe.Test.main(Test.java:16)看看Collectors.toMap()方法的源码,如下:publicstaticCollector>toMap(FunctionkeyMapper,FunctionvalueMapper,BinaryOperatormergeFunction){returntoMap(keyMapper,valueMapper,mergeFunction,HashMap::new);}默认会创建一个HashMap,继续查看源码:publicstatic>CollectortoMap(FunctionkeyMapper,函数valueMapper,BinaryOperatormergeFunction,SuppliermapSupplier){BiConsumer累加器=(map,element)->map.merge(keyMapper.apply(element),valueMapper.apply(element),合并函数);returnnewCollectorImpl<>(mapSupplier,accumulator,mapMerger(mergeFunction),CH_ID);}通过Map.merge()方法来合并,源码如下:defaultVmerge(Kkey,Vvalue,BiFunctionremappingFunction){Objects.requireNonNull(remappingFunction);Objects.requireNonNull(值);VoldValue=get(key);VnewValue=(oldValue==null)?值:remappingFunction.apply(oldValue,value);如果(newValue==null){删除(键);}else{put(key,newValue);}返回newValue;}可以看到在merge()方法中,value值不能为空Objects.requireNonNull(value);继续看Objects.requireNonNull()方法的源码publicstaticTrequireNonNull(Tobj){if(obj==null)thrownewNullPointerException();returnobj;}如果值为空,直接报NullPointerException那么,如何解决这个空指针异常问题呢?一般有两种方式:(1)用默认值替换空值,比如0packagecom.magic.npe;importjava.util.ArrayList;importjava.util.List;importjava.util.Map;import爪哇。util.Optional;importjava.util.stream.Collectors;publicclassTest{publicstaticvoidmain(String[]args){Liststudents=newArrayList<>();students.add(newStudent("张三",18));students.add(newStudent("李四",21));students.add(newStudent("王舞",null));//如果age为null,直接赋默认值Value0MapstudentMap=students.stream().collect(Collectors.toMap(Student::getName,s->Optional.ofNullable(s.getAge()).orElse(0)));系统。out.println(studentMap);}}运行程序,可以看到如下输出{李四=21,张三=18,王五=0}(2)调用collect()的其他实现方法packagecom.magic.npe;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;publicclassTest{publicstaticvoidmain(String[]args){List<学生>学生=新的ArrayList<>();students.add(newStudent("张三",18));students.add(newStudent("李四",21));students.add(newStudent("王舞",null));MapstudentMap=students.stream().collect(HashMap::new,(map,student)->map.put(student.getName(),student.getAge()),HashMap::putAll);System.out.println(studentMap);}}运行程序,可以看到如下输出{LiSi=21,ZhangSan=18,WangWu=null}