Java Stream API映射处理核心是生成新结构而非修改原对象:map用于一对一转换,flatMap扁平化嵌套结构,toMap构建键值映射,groupingBy实现分组聚合。

Java Stream API 的映射处理核心在于把对象流中的每个元素按需转换,关键不是“改原对象”,而是生成新结构——比如提取字段、计算值、构造新对象,或进一步聚合成 Map、List 等容器。
用 map 提取或转换字段
map 是最常用的映射操作,适用于一对一转换。它接收一个 Function,对每个元素执行映射逻辑,返回新流。
- 提取属性:如
stream.map(Person::getName)得到Stream<string></string> - 类型转换:如
stream.map(p -> new NameDto(p.getName()))构造新 DTO 对象 - 链式转换:可连续 map,例如先取名再转大写再算长度:
.map(Person::getName).map(String::toUpperCase).map(String::length) - 注意返回类型必须明确:lambda 或方法引用的返回值决定新流的泛型,编译器据此推断
用 flatMap 展开嵌套结构
当单个对象对应多个结果(比如一个订单含多个商品),map 会产出 Stream<stream>></stream>,这时需 flatMap 扁平化。
- 典型场景:把
List<order></order>映射为所有订单项的扁平列表 - 写法示例:
orders.stream().flatMap(o -> o.getItems().stream()) - 本质是“先映射成流,再合并所有子流”,避免手动嵌套循环或 collect 后再遍历
- flatMap 的参数函数必须返回 Stream,不能返回普通集合或数组(除非显式调用 .stream())
用 Collectors.toMap 构建键值映射
当需要把对象流转为 Map 时,toMap 是专用工具,需明确定义键、值及冲突策略。
立即学习“Java免费学习笔记(深入)”;
- 基础用法:
stream.collect(toMap(Person::getId, p -> p)),以 id 为键,Person 自身为值 - 键值可不同:如
toMap(Person::getEmail, Person::getAge)得到Map<string integer></string> - 重复键必须处理:第三个参数指定合并逻辑,例如
(v1, v2) -> v1保留第一个 - 空值敏感:键或值为 null 会抛
NullPointerException,必要时先 filter 排除
用 groupingBy 按条件分组聚合
groupingBy 不是映射操作本身,但常与映射配合使用,尤其适合按复合键、衍生键归类对象。
- 直接传分类函数:
stream.collect(groupingBy(p -> p.getDept() + "-" + p.getLevel())) - 避免先 map 再 groupingBy:那样会丢失原始对象,导致无法分组;应让分类函数直接作用于原对象
- 可定制下游收集器:如
groupingBy(keyFunc, LinkedHashMap::new, mapping(Person::getName, joining(", ")))实现有序 + 拼接姓名 - 键函数务必纯且稳定:相同输入必须返回相同输出,否则分组结果不可靠


















