Collectors.toMap()引起的NullPointerException

环境说明

  • JDK1.8
  • Collectors.toMap()方法

问题复现

当使用Stream的collect()收集的时可以传入自定义收集器,这个时候就可以使用Collectors工具类中的各种生成自定义收集器的静态方法。toMap()就是用来生成可以收集指定key和value的收集器的。

@Test
    public void toMap_Test(){
        person person1=new person();
        person1.name="张三";
        person1.address="北京";
        person person2=new person();
        person2.name="李四";
        person2.address=null;   //注意
        person person3=new person();
        person3.name="张三";
        person3.address="广州";
        HashMap<String, String> NameAddressMap = Arrays.asList(person1, person2, person3).stream().
                collect(Collectors.toMap(person::getName, person::getAddress, (olderValue, replaceValue) -> olderValue, HashMap::new));
    }

报错:
在这里插入图片描述

toMap()源码

//其他的重载方法底层调用也是这个方法
/** 
	Params:   keyMapper:key的映射函数
			  valueMapper:value的映射函数
			  mergetFunction:合并函数(当向map中插入存在的Key的时候,使用该函数提供的解决方案)
			  mapSupplier:map实例提供函数
*/
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是HashMap,不管key是否发生冲突,总会调用响应map实现类的中的merge()方法来合并数据,mege()方法会检查元素的value是否为null,而不是key为null。而且HashMap中key为null是可以保存的,所以当你收集的数据中指定的value的这个字段如果为null就会报NullPointerException。

//HashMap中的merge方法的部分代码
 @Override
    public V merge(K key, V value,
                   BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        if (value == null)
            throw new NullPointerException();
        if (remappingFunction == null)
            throw new NullPointerException();
        int hash = hash(key);
        ....
       }

解决方案

如果没有提供mergeFunction方法的话,当key重新重复的时候,默认使用throwingMerger()抛出异常
在这里插入图片描述

在收集前过滤掉指定value的字段为null的数据,把NullPointerException异常提前,这样就可以根据日志更好的定位问题。

HashMap<String, String> NameAddressMap = Arrays.asList(person1, person2, person3).stream().
                filter(person -> {
                    if(person.getAddress()==null){
                       log.error("{}数据为null,请检查",person.getName());
                    }
                    return true;
                }).
                collect(Collectors.toMap(person::getName, person::getAddress, (olderValue, replaceValue) -> olderValue, HashMap::new));
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值