点击上方"程序员蜗牛g",选择"设为星标"
跟蜗牛哥一起,每天进步一点点

程序员蜗牛g
大厂程序员一枚 跟蜗牛一起 每天进步一点点
33篇原创内容
**
公众号
本篇文章将详细的介绍flatMap函数的各种场景下的使用。
假设你有一个List<List>,而你想要得到一个包含所有字符串的单一列表。大多数开发者会在这里使用flatMap,如下示例:
less
List<List<String>> names = List.of( List.of("张三", "李四"), List.of("曹查理", "大卫"), List.of("女娲", "Jerry"));// 使用流(Stream)将嵌套的列表展平为一个单一的字符串列表List<String> flattened = names.stream() .flatMap(List::stream) // 将每个子列表中的元素"拉平"到一个流中 .toList(); // 收集结果为一个新列表// 输出展平后的结果System.out.println(flattened);
输出结果
css
[张三, 李四, 曹查理, 大卫, 女娲, Jerry]
这是最基础用法。我们没有得到一个Stream<List>,而是将其"扁平化"成了一个单一的Stream。**
**
使用Optional时的flatMap技巧
如果你正在使用一个可能存在也可能不存在的数据时。你可能会用 Optional 来处理这种情况。但是,如果你需要串联多个操作呢?
通常情况下,你会得到嵌套的Optional<Optional>,这看起来就很头大。而这正是flatMap大显身手的地方。如下示例:
vbnet
public static void main(String[] args) { Optional<String> nameOpt = Optional.of("Spring Boot3实战案例200讲"); Optional<Optional<String>> result = nameOpt .map(FlatMapDemo2::toUpperCase); // ❌ 得到嵌套的 Optional System.out.println(result);}public static Optional<String> toUpperCase(String s) { if (s == null || s.isEmpty()) { return Optional.empty(); } return Optional.of(s.toLowerCase());}
输出结果
python
Optional[Optional[spring boot3实战案例200讲]]
使用flatMap
vbnet
Optional<String> nameOpt = Optional.of("Spring Boot3实战案例200讲");Optional<String> result = nameOpt.flatMap(FlatMapDemo2::toUpperCase) ;System.err.println(result) ;
输出结果
css
Optional[spring boot3实战案例200讲]
总结:
- map:会对结果进行包装,从而产生嵌套结构。
- flatMap:会解开包装,保持简洁。
flatMap替代嵌套循环
嵌套循环,会损害代码的可读性,尤其是在处理多维数据时。而flatMap可以用一种更优雅的方式替代它们。
如下示例:两个列表的笛卡尔积,假设你想要生成产品及其所有颜色组合的列表。
less
List<String> products = List.of("IPad", "IPhone", "Book");List<String> colors = List.of("黑色", "白色");List<String> result = products.stream() .flatMap(product -> colors.stream() .map(color -> product + " - " + color)) .collect(Collectors.toList());result.forEach(System.out::println);
输出结果
IPad - 黑色IPad - 白色IPhone - 黑色IPhone - 白色Book - 黑色Book - 白色
如果不使用flatMap,你就得编写嵌套循环。而使用flatMap后,代码会变得清晰、简洁且具有函数式风格。**
**
flatMap处理API响应
在实际应用中,你经常需要从可能返回列表、可选字段或嵌套结构的API中获取数据。你可以使用flatMap直接转换并扁平化结果,而无需进行空值检查。
如下示例:扁平化API数据,假设有一个User类,其中包含一个返回电话号码列表的方法:
arduino
public static void main(String[] args) { List<User> users = List.of( new User("Pack_xg", Arrays.asList("111", "222")), new User("pack", Arrays.asList("333")), new User("xg", Arrays.asList("444", "555")) ); List<String> result = users.stream() .flatMap(user -> user.phones().stream()) .toList() ; System.out.println(result);}public static record User(String name, List<String> phones) {}
输出结果
csharp
[111, 222, 333, 444, 555]
如果你用for循环实现此功能,代码会显得臃肿。而借助flatMap,只需一行代码就能完成转换。**
**
flatMap + filter:秘密武器
大多数开发者会使用filter和map,但很少将它们与flatMap结合使用。而正是这种结合能让你解锁另一层强大功能。如下示例:提取有效电子邮件地址
less
List<List<String>> emails = List.of( List.of("pack_xg@gmail.com", "www.qq.com"), List.of("pack@yahoo.com"), List.of("xg@", "xxxooo@qq.com"));List<String> result = emails.stream() .flatMap(List::stream) .filter(email -> email.contains("@") && email.contains(".")) .toList() ;System.out.println(result);
输出结果
perl
[pack_xg@gmail.com, pack@yahoo.com, xxxooo@qq.com]
我们无需逐个验证嵌套列表中的元素,而是可以在一个操作链中完成扁平化、过滤和收集。
综合示例
你需要获取用户数据;每个用户都有若干订单;每个订单都包含若干产品。而你想要得到一个扁平化的列表,其中包含所有用户购买的所有产品的名称。
准备如下类:
vbnet
//商品public record Product(String name) {}//订单public record Order(List<Product> products) {}//用户public record User(String name, List<Order> orders) {}
准备数据
sql
List<Product> p1 = List.of( new Product("iPhone 15"), new Product("AirPods Pro"));List<Product> p2 = List.of( new Product("MacBook Pro"));List<Order> o1 = List.of( new Order(p1), new Order(p2));User zhangsan = new User("张三", o1);List<Product> lisiProducts1 = List.of( new Product("iPad Air"), new Product("Apple Watch"));List<Order> o2 = List.of( new Order(lisiProducts1));User lisi = new User("李四", o2);User wangwu = new User("王五", List.of());// 所有用户List<User> users = List.of(zhangsan, lisi, wangwu) ;
传统做法
css
List<String> productNames = new ArrayList<>();for (User user : users) { for (Order order : user.orders()) { for (Product product : order.products()) { productNames.add(product.name()); } }}System.err.println(productNames) ;
使用flatMap
scss
List<String> productNames = users.stream() .flatMap(user -> user.orders().stream()) .flatMap(order -> order.products().stream()) .map(Product::name) .toList() ;
总结:掌握flatMap不仅会让你的代码更简洁------它还会改变你的思维方式。你将不再编写那些千篇一律的循环代码。
如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、转发、在看。
关注公众号:woniuxgg,在公众号中回复:笔记 就可以获得蜗牛为你精心准备的java实战语雀笔记,回复面试、开发手册、有超赞的粉丝福利!