首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Stream 强大,Map 精妙,但千万别碰 toMap()!

嗨,我是东哥。

今天要跟大家聊聊 Java 8 中的 Stream 流处理。作为一名老程序员,Stream 是真的美妙,但有一个地方你得注意,那就是别用 toMap() 方法。不信?那让我们一起来看看这个折腾人的故事。

# Java 8 引入的 Stream

自从 Java 8 引入了 Stream 这个功能,代码简洁程度飞跃了好几个台阶。Stream 流式操作简直是救了我这条懒得动的老命,从此我可以优雅地进行各种数据处理,尤其是在集合数据的处理上,真是事半功倍。

平时我们用 Stream 最常见的操作无非是 collect(Collectors.toList()) 和 collect(Collectors.toSet()),这让我们在处理集合数据时非常方便快捷。但是,当你尝试使用 toMap() 时,事情就没那么简单了。

别用 toMap() 的原因

你可能会想,既然 toList 和 toSet 都这么好用,toMap() 也应该差不多吧?事实是,一旦你用错了,麻烦就来了。

首先,让我们看一个简单的示例。我们有一个用户实体类,结构如下:

@Data@AllArgsConstructor public class User { private int id; private String name; }

假设我们从数据库中读取了一个用户列表,并希望将其转换为 Map,其中 key 是用户的 id,value 是用户的 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 值重复。

Key 重复的处理

作为资深程序员,第一反应是检查 HashMap 的机制,Key 重复应该进行替换才对啊。于是,我们尝试修改代码来手动处理重复 Key 的情况:

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, (oldData, newData) -> newData)); System.out.println(map); }}

然而,再次运行时,你发现又出现了新的问题——NullPointerException (NPE)。这时候你会发现原来 User::getName 可能会返回 null 值。

使用 Optional 避免 NPE

为了避免 NPE,我们可以使用 Optional 来包装 null 值:

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, user -> Optional.ofNullable(user.getName()).orElse(""), (oldData, newData) -> newData) ); System.out.println(map); }}

这段代码看起来是优雅了不少,但你真的需要这么复杂的处理吗?用 Stream 和 Optional 确实能解决问题,但也可能让代码的可读性变得差。

回归传统 for 循环

最后,我们还是得承认,有时候传统的 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(user -> { map.put(user.getId(), user.getName() != null ? user.getName() : ""); }); System.out.println(map); }}

这段代码不仅易于理解,而且避免了很多潜在的问题。

# 结论

虽然 Stream 的 toMap() 方法提供了一种简洁的方式将流转换为 Map,但在处理重复 Key 和 null 值时需要特别小心。某些情况下,回归传统的 for 循环可能会让代码更加清晰明了。

所以,东哥劝你一句,尽量避免使用 toMap(),在需要的时候多考虑一下传统的方式。祝大家编码愉快,别被 Stream 玩坏了!‍

怎么样,各位大佬,你们在开发中有没有遇到过类似的问题?欢迎在评论区分享你们的经验和见解!

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OewowPpdyas2uFz_MlWhFI1g0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券