包阅导读总结
1. 关键词:JDK 8、Stream、toMap、异常、循环
2. 总结:
本文以将用户集合转为 Map 结构数据为例,展示了使用 `toMap` 方法时遇到的问题,包括键值重复导致的 `IllegalStateException` 和空值导致的 `NPE`,虽经多次修改仍复杂易错,最终发现简单的循环就能解决,却仍选择用 `Stream` 提交代码。
3. 主要内容:
– JDK 8 引入的 Stream 流处理在日常开发中常用
– 流处理后返回集成对象时常用 `collect(Collectors.toList())` 或 `collect(Collectors.toSet())`
– 尝试使用 `toMap` 处理用户集合转 Map 结构数据
– 遇到的问题
– 键值重复报错 `IllegalStateException`
– 处理重复场景后出现空值导致 `NPE`
– 最终结果
– 发现一个循环就能解决问题
– 但仍选择用复杂的 `Stream` 与 `Optional` 并提交代码
思维导图:
文章地址:https://juejin.cn/post/7383643463534018579
文章来源:juejin.cn
作者:烽火戏诸诸诸侯
发布时间:2024/6/24 12:41
语言:中文
总字数:984字
预计阅读时间:4分钟
评分:83分
标签:后端,Java
以下为原文内容
本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com
在 JDK 8
中 Java
引入了让人欲罢不能的 stream
流处理,可以说已经成为了我日常开发中不可或缺的一部分。
当完成一次流处理之后需要返回一个集成对象时,已经肌肉记忆的敲下 collect(Collectors.toList())
或者 collect(Collectors.toSet())
。你可能会想,toList
和 toSet
都这么便捷顺手了,当又怎么能少得了 toMap()
呢。
答应我,一定打消你的这个想法,否则这将成为你噩梦的开端。
什么?你不信,没有什么比代码让人更痛彻心扉,让我们直接上代码。
让我们先准备一个用户实体类。
@Data@AllArgsConstructor public class User { private int id; private String name; }
假设有这么一个场景,你从数据库读取 User
集合,你需要将其转为 Map
结构数据,key
和 value
分别为 user
的 id
和 name
。
很快,你啪的一下就写出了下面的代码:
public class UserTest { @Test public void demo() { List<User> userList = new ArrayList<>(); userList.add(new User(1, "Alex")); userList.add(new User(1, "Beth")); Map<Integer, String> map = userList.stream() .collect(Collectors.toMap(User::getId, User::getName)); System.out.println(map); }}
运行程序,你已经想好了开始怎么摸鱼,结果啪的一下 IllegalStateException
报错就拍你脸上,你定睛一看怎么提示 Key
值重复。
作为优秀的八股文选手,你清楚的记得 HashMap
对象 Key
重复是进行替换。你不信邪,断点一打,堆栈一看,硕大的 uniqKeys
摆在了面前,凭借四级 424
分的优秀战绩你顿时菊花一紧,点开一看,谁家好人 map key
还要去重判断啊。
好好好,这么玩是吧,你转身打开浏览器一搜,原来需要自己手动处理重复场景,啪的一下你又重新改了一下代码:
public class UserTest { @Test public void demo() { List<User> userList = new ArrayList<>(); userList.add(new User(1, "Alex")); userList.add(new User(2, null)); Map<Integer, String> map = userList.stream() .collect(Collectors.toMap(User::getId, User::getName, (oldData, newData) -> newData)); System.out.println(map); }}
再次执行程序,你似乎已经看到知乎的摸鱼贴在向你招手了,结果啪的一下 NPE
又拍在你那笑容渐渐消失的脸上。
静下心来,本着什么大风大浪我没见过的心态,断点堆栈一气呵成,而下一秒你又望着代码陷入了沉思,我是谁?我在干什么?
鼓起勇气,你还不信今天就过不去这个坎了,大手一挥,又一段优雅的代码孕育而生。
public class UserTest { @Test public void demo() { List<User> userList = new ArrayList<>(); userList.add(new User(1, "Alex")); userList.add(new User(1, "Beth")); userList.add(new User(2, null)); Map<Integer, String> map = userList.stream() .collect(Collectors.toMap( User::getId, it -> Optional.ofNullable(it.getName()).orElse(""), (oldData, newData) -> newData) ); System.out.println(map); }}
优雅,真是太优雅了,又是 Stream
又是 Optional
,可谓是狠狠拿捏技术博文的 G
点了。
这时候你回头一看,我需要是什么来着?这 TM
不是一个循环就万事大吉了吗,不信邪的你回归初心,回归了 for
循环的怀抱,又写了一版。
public class UserTest { @Test public void demo() { List<User> userList = new ArrayList<>(); userList.add(new User(1, "Alex")); userList.add(new User(1, "Beth")); userList.add(new User(2, null)); Map<Integer, String> map = new HashMap<>(); userList.forEach(it -> { map.put(it.getId(), it.getName()); }); System.out.println(map); }}
看着运行完美无缺的代码,你一时陷入了沉思,数分钟过去了,你删除了 for
循环,换上 Stream
与 Optional
不羁的外衣,安心的提交了代码,这口细糠一定也要让好同事去尝一尝。