嵌套流处理核心是职责分明:flatMap展开、map提取、filter/collect实现逻辑;flatMap须返回Stream且防null;提取字段需显式lambda判空;操作应在扁平后进行;Map嵌套同理逐层转流。

嵌套流处理的关键不是“一层层写下去”,而是明确每一步的职责:用 flatMap 展开集合,用 map 提取字段,用 filter/collect 实现业务逻辑。路径清晰、空值可控、语义明确,比代码短更重要。
用 flatMap 逐层拉平嵌套结构
flatMap 的本质是“映射成流 + 合并”,不是简单压平。它要求函数返回 Stream<?>,不能返回 List 或普通对象。
- 两层嵌套(如部门→员工):用
.flatMap(dept -> dept.getEmployees().stream()) - 三层嵌套(如部门→员工→任务):再加一次
.flatMap(emp -> emp.getTasks().stream()) - 若某级字段可能为 null,必须提前防护,比如:
.flatMap(emp -> Optional.ofNullable(emp.getTasks()).orElse(List.of()).stream())
提取字段时注意空安全与路径显式
嵌套字段访问不能靠方法引用链(如 Task::getProject::getId),必须用 lambda 显式判断 null。
- 按 Project ID 分组:用
Collectors.groupingBy(t -> t.getProject() != null ? t.getProject().getId() : -1) - 对 BigDecimal 求和:推荐用
Optional嵌套导航,避免 NPE,例如:t -> Optional.ofNullable(t.getFulfillment()).map(f -> Optional.ofNullable(f.getStoreDelivery()).map(sd -> sd.getCost()).orElse(BigDecimal.ZERO)).orElse(BigDecimal.ZERO).doubleValue()
去重、筛选、聚合要选对操作位置
扁平后才是操作数据的起点,别在展开前就 filter 错层级。
立即学习“Java免费学习笔记(深入)”;
- 提取所有城市名并去重:
employees.stream().flatMap(e -> e.getAddresses().stream()).map(Address::getCity).collect(Collectors.toSet()) - 只取 JPG 图片 URL:
products.stream().flatMap(p -> p.getImages().stream()).flatMap(i -> i.getTypes().stream()).filter("jpg"::equalsIgnoreCase).map(ImageType::getUrl).collect(Collectors.joining(",")) - 需要排序或限制数量:在 map 后接
.sorted().limit(10).collect(Collectors.toList())
Map 嵌套也能 flatMap,但入口要对
处理 Map<K, Map<A, List<B>>> 这类结构,关键是把每层“值”转为流。
- 先
entrySet().stream()得到外层键值对流 - 再
.flatMap(e -> e.getValue().entrySet().stream())展开内层 Map - 最后
.flatMap(e2 -> e2.getValue().stream())展开 List<B> - 全程用 map 组装最终结果,比如
.map(b -> new Tuple3(e.getKey(), e2.getKey(), b))


















