大家好,我是大华。 最近在公司做代码review的时候,几个同事在使用Stream.toMap()
时踩了坑。有的甚至直接说:"这玩意儿太坑了,我宁愿写 for 循环!"
其实toMap()
没那么可怕,今天分享3个避坑案例。看完你也就能放心用了!
1. 重复key直接报错
那天小王写了个这样的代码:
java
List<User> userList = Arrays.asList(
new User(1, "张三"),
new User(2, "李四"),
new User(1, "王五") // 注意:重复的ID
);
// 转map
Map<Integer, String> map = userList.stream()
.collect(Collectors.toMap(User::getId, User::getName));
一运行,直接崩了!抛出一堆Duplicate key
的异常。
解决方案:加个合并函数就行
java
Map<Integer, String> map = userList.stream()
.collect(Collectors.toMap(
User::getId,
User::getName,
(oldValue, newValue) -> oldValue // 重复时保留旧值
));
效果对比 : 原代码 :直接抛出异常Duplicate key 张三(attempted merging values 张三 and 王五)
。 解决后 :成功生成Map
,内容为{1=张三, 2=李四}
(保留了第一个出现的值)。
这样当key
重复时,会自动处理而不是直接报错。 根据需求,你也可以选择覆盖:(oldValue, newValue) -> newValue
,这样结果就会是{1=王五, 2=李四}
(保留最后一个值)
2. 空指针异常
小李遇到了更头疼的问题:
java
List<Product> products = getProducts(); // 可能返回null值列表
Map<Long, String> productMap = products.stream()
.collect(Collectors.toMap(Product::getId, Product::getName));
如果列表里有null
元素,直接NullPointerException
!
解决方案: 先用filter
过滤掉null
java
Map<Long, String> productMap = products.stream()
.filter(Objects::nonNull) // 先过滤null
.collect(Collectors.toMap(
Product::getId,
Product::getName,
(oldValue, newValue) -> newValue
));
效果对比 : 原代码 :遇到null
元素直接抛出NullPointerException
。 解决后 :自动跳过null
元素,只处理有效数据生成Map
。
这样简单的一步,就可以告别空指针!
3. 想要转换特定Map类型
小张需要返回一个有序的LinkedHashMap
,但toMap()
默认返回HashMap
,怎么办?
解决方案: 指定具体Map
类型
java
Map<Integer, User> userMap = userList.stream()
.filter(Objects::nonNull)
.collect(Collectors.toMap(
User::getId,
Function.identity(), // 直接取对象本身
(oldValue, newValue) -> newValue,
LinkedHashMap::new // 指定Map类型
));
效果对比 : 原代码 :返回HashMap
,遍历顺序不确定。 解决后 :返回LinkedHashMap
,保持元素插入顺序,比如:
java
// 遍历时保证按 张三、李四、王五的顺序
userMap.forEach((id, user) -> System.out.println(user.getName()));
这样就能得到保持插入顺序的LinkedHashMap
了。
总结
toMap()
其实很好用,只要记住这三个点就可以:
- 有重复
key
时:记得加合并函数(oldValue, newValue) -> ...
- 可能有空元素时:先用
filter(Objects::nonNull)
过滤 - 需要特定
Map
类型时:第四个参数指定如LinkedHashMap::new
以后再遇到toMap()
,就不用绕道走了。这几个技巧掌握后,你就能优雅地使用它了! PS: 文中代码基于Java8+
,如果你用的是旧版本...建议升级,很多新特性真的很好用!
觉得有帮助的话,点个收藏分享给更多小伙伴吧~还有什么问题欢迎留言讨论!
我是大华,专注分享前后端开发的实战笔记。关注我,少走弯路,一起进步!
📌往期精彩
《工作 5 年没碰过分布式锁,是我太菜还是公司太稳?网友:太真实了!》
《写给小公司前端的 UI 规范:别让页面丑得自己都看不下去》
《只会写 Mapper 就敢说会 MyBatis?面试官:原理都没懂》