在使用java8的stream处理集合的时候,遇到了java8的一个坑:使用Collectors.toMap的时候value不能为null,这个不知道算不算bug,不过在java9中已经完善了。
在工作中,你一定会经常碰到从数据库中取出List类型的数据然后加工处理。为了说明这次的问题,我把数据模型简化了给大家描述,现在定义一个简单的实体类
![dbbdaa93dd3e0949582cb8da1fb8752a.png](https://i-blog.csdnimg.cn/blog_migrate/ad9ef5d9a1a644c0bd556cb92b2c7f56.jpeg)
![4b8c7d5a39efe96d164838650904ebba.png](https://i-blog.csdnimg.cn/blog_migrate/871e5228d5481930f4b0a98012c22fb2.jpeg)
这时候如果你想把这组数据提取出userId为key、nickName为value的Map类型,使用传统的遍历当然可以,只是java8这种新特性使用一次就爱不释手了,只需要一行代码就可以搞定:
Map nickNameMap = userList.stream().collect(Collectors.toMap(UserInfo::getUserId, UserInfo::getNickName));
是不是很方便,但是有一天你发现这代码抛出了NullPointerException,心理会不会吐槽这代码前几天还运行的好好的。这种情况可能就是你的value为空了,Collectors.tomap点进源码看看
![49216aca8a4ca54a3e6642d75247a113.png](https://i-blog.csdnimg.cn/blog_migrate/60c91c8c61fab59dbf6e0eab9ea62341.jpeg)
map.merge里要求value不能为空,否则抛错。学学孔乙己,我们也列举几种解决写法
1.Map nickNameMap2 = userList.stream().collect(Collectors.toMap(UserInfo::getUserId, s -> Optional.ofNullable(s).map(UserInfo::getNickName).orElse(""))); 这种方式可以避免value为null抛错的情况2.Map nickNameMap = userList.stream().collect(HashMap::new, (k, v) -> k.put(v.getUserId(), v.getNickName()), HashMap::putAll); 这种写法可以避免key重复的问题,key重复的话后值会覆盖前值
下边列出几种常见的场景写法:
1. 取出所有的userId并去重 List userIds = userList.stream().map(UserInfo::getUserId).distinct().collect(Collectors.toList());2.遍历修改元素 userList.stream().forEach(s -> s.setNickName(s.getNickName() + "_hello"));3.条件性修改元素 userList.stream().filter(s -> (s.getUserId().equals("1111111"))).forEach(s -> s.setNickName("我又修改了"));