惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
罗磊的独立博客
H
Help Net Security
I
Intezer
G
Google Developers Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
Troy Hunt's Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
U
Unit 42
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
N
News and Events Feed by Topic
J
Java Code Geeks
S
Security Affairs
T
The Blog of Author Tim Ferriss
Recent Commits to openclaw:main
Recent Commits to openclaw:main
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
D
Docker
The GitHub Blog
The GitHub Blog
F
Full Disclosure
N
News and Events Feed by Topic
Webroot Blog
Webroot Blog
S
Security @ Cisco Blogs
腾讯CDC
人人都是产品经理
人人都是产品经理
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
T
Threatpost
D
DataBreaches.Net
Recent Announcements
Recent Announcements
博客园 - 三生石上(FineUI控件)
MongoDB | Blog
MongoDB | Blog
博客园 - 【当耐特】
L
LINUX DO - 最新话题
Google Online Security Blog
Google Online Security Blog
S
Schneier on Security
S
Securelist
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Help Net Security
Help Net Security
P
Proofpoint News Feed
Project Zero
Project Zero
S
SegmentFault 最新的问题
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MyScale Blog
MyScale Blog
Google DeepMind News
Google DeepMind News
宝玉的分享
宝玉的分享
Y
Y Combinator Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 叶小钗

Hsu Yeung 的博客

三圣花市 | Hsu Yeung 的博客 网站支持 Live Photo 图片展示 | Hsu Yeung 的博客 梦 | Hsu Yeung 的博客 周末午餐 | Hsu Yeung 的博客 张家界 | Hsu Yeung 的博客 话剧《寻她芳踪·张爱玲》 | Hsu Yeung 的博客 博客自动生成文章目录 | Hsu Yeung 的博客 灭螂行动! | Hsu Yeung 的博客 张靓颖成都演唱会 | Hsu Yeung 的博客 最近对博客做的一些微调总结 | Hsu Yeung 的博客 Windows 上安装 Lua | Hsu Yeung 的博客 网站支持展示 B 站 iframe 视频 SpringBoot 中使用 RedisTemplate 存取整数值的坑 | Hsu Yeung 的博客 SQL JOIN 中 ON 与 WHERE 的区别 值得记录的一些工作近况 | Hsu Yeung 的博客 周传雄成都演唱会 | Hsu Yeung 的博客 并行操作导致获取数据库连接超时 | Hsu Yeung 的博客 风信子 | Hsu Yeung 的博客 Linux 安装并配置 Nginx | Hsu Yeung 的博客 使用 logrotate 切割 nginx 日志 郁金香土培结果 | Hsu Yeung 的博客 MySQL LEFT JOIN 右表有多条数据但只取最新的一条 | Hsu Yeung 的博客 获取数据库锁等待超时问题 | Hsu Yeung 的博客 从零开始挑选相机 | Hsu Yeung 的博客 郁金香 | Hsu Yeung 的博客 我的第一束花 | Hsu Yeung 的博客 快乐的一周 | Hsu Yeung 的博客 重庆,来了 | Hsu Yeung 的博客 散步 | Hsu Yeung 的博客 Git 工作区、暂存区、版本库之间的关系 | Hsu Yeung 的博客 AOP 记录请求参数时序列化异常问题 | Hsu Yeung 的博客 第一次参加演唱会 | Hsu Yeung 的博客 MySQL FIND_IN_SET 函数的使用 | Hsu Yeung 的博客 自动拆箱机制导致编译失败 | Hsu Yeung 的博客 最近 | Hsu Yeung 的博客 夜爬龙泉山 | Hsu Yeung 的博客 在 Windows 上安装多个版本 JDK 并切换使用的版本 安装 Windows Terminal 和 gsudo 记录 意外的奖励 | Hsu Yeung 的博客 记第一次修热水器 | Hsu Yeung 的博客 在 Windows 电脑上调试 iPhone Safari 浏览器的网页 给网站加上 RSS | Hsu Yeung 的博客 打雷了 | Hsu Yeung 的博客 豉汁蒸排骨 | Hsu Yeung 的博客 我的 2022 年 | Hsu Yeung 的博客 如何使用 Git 给代码打 tag | Hsu Yeung 的博客 记一次有趣的上班经历 | Hsu Yeung 的博客 我记得 | Hsu Yeung 的博客 Spring 新增或修改请求 header 参数 | Hsu Yeung 的博客 Spring 事务传播机制 | Hsu Yeung 的博客 在家自制“周黑鸭” | Hsu Yeung 的博客 晚餐 | Hsu Yeung 的博客 如何解决逻辑删除与数据库唯一约束冲突 | Hsu Yeung 的博客 [转]漫画赏析:Linux 内核到底长啥样 | Hsu Yeung 的博客 数据库逻辑设计之三大范式通俗理解 | Hsu Yeung 的博客 计算机中的大小端是指什么 | Hsu Yeung 的博客 MySQL 学习笔记 | Hsu Yeung 的博客 [转]《玉子市场》的人物魅力 | Hsu Yeung 的博客 Linux 安装 Redis | Hsu Yeung 的博客 Linux 安装 MySQL | Hsu Yeung 的博客 Linux 安装 JDK | Hsu Yeung 的博客 [转]Thymeleaf 表达式工具类 | Hsu Yeung 的博客 Shell 基础入门介绍 | Hsu Yeung 的博客 Linux 中的软链接和硬链接 | Hsu Yeung 的博客 MySQL 将某些字段的值排在最前或最后 | Hsu Yeung 的博客 数据结构与算法学习笔记 | Hsu Yeung 的博客 Visual Studio Code 如何编写运行 C 程序?
Collectors.toMap() 操作 value 为 null 的情况
2023-10-24 · via Hsu Yeung 的博客

记录一下 Java8 Stream 流操作中 Collectors.toMap() 操作当 value 为 null 时报空指针的问题以及解决方案。

问题代码:

@Override
public Map<Long, String> getEmployeeIdCompanyLicenseNoMap(Collection<Long> employeeIds) {
    if (CollectionUtils.isEmpty(employeeIds)) {
        return Collections.emptyMap();
    }
    List<EmployeeCompanyLicenseNoDTO> relationList = baseMapper.getEmployeeCompanyLicenseNoList(employeeIds);
    if (CollectionUtils.isEmpty(relationList)) {
        return Collections.emptyMap();
    }
    return relationList
            .stream()
            .collect(Collectors.toMap( 
                    EmployeeCompanyLicenseNoDTO::getEmployeeId,
                    EmployeeCompanyLicenseNoDTO::getCompanyLicenseNo);
}

上面这段代码目的是查询员工 id 与其所属公司的营业执照编号的对应关系。其中有些员工是没有公司的,查询出来的营业执照编号将是 null。

运行这段代码后收到一个空指针异常,断点查看 relationList 的数据,其中有部分数据的 companyLicenseNo 字段值为 null。很是疑惑,之前用了那么久的 toMap 方法都没有问题呀?而且 Map 的 value 是允许有多个 null 值的呀?为什么这里就不行了。光是想肯定没有用,带着这些疑问点开源码,看看最终是哪一步调用导致的空指针异常。

Collectors.toMap() 方法
Collectors.toMap() 方法

从图中可以看出来,最终实际上是调用的图片右侧的 toMap 方法,可以看到右侧绿色框的代码,有一句 (map, element) -> map.merge(keyMapper.apply(element),,而 map 根据函数签名上的泛型定义 public static <T, K, U, M extends Map<K, U>> 可以知道,map 变量表示的是 Map 接口,并且调用了 Map 接口的 merge 方法。跟着点开对应源码:

Map 的 merge() 方法定义
Map 的 merge() 方法定义

可以看到,Map 接口中 merge 方法有个默认实现,其中对 value 进行了判空的操作,但是我们可以这里调用 toMap 操作的时候默认 new 的是 HashMap 的实例。而 HashMap 是 Map 的实现类之一,因此我们点开 HashMap 的 merge 方法。

HashMap 的 merge() 方法实现
HashMap 的 merge() 方法实现

可以看到 HashMapmerge 方法也是对 value 进行了判空操作的,因此问题的原因也就找到了。

在网上找了一圈,最终采用的解决方案就是放入 value 的时候判断一下,如果是 null 则放入一个空字符串或者是其他不具有业务含义的值来代替。

以下是其中一种写法:

@Override
public Map<Long, String> getEmployeeIdCompanyLicenseNoMap(Collection<Long> employeeIds) {
    if (CollectionUtils.isEmpty(employeeIds)) {
        return Collections.emptyMap();
    }
    List<EmployeeCompanyLicenseNoDTO> list = baseMapper.getEmployeeCompanyLicenseNoList(employeeIds);
    if (CollectionUtils.isEmpty(list)) {
        return Collections.emptyMap();
    }
    return list
            .stream()
            .collect(Collectors.toMap(
                    EmployeeCompanyLicenseNoDTO::getEmployeeId,
                    it -> Optional.ofNullable(it.getCompanyLicenseNo()).orElse(CommonConstant.EMPTY_STR)));
}