可使用Collectors.groupingBy配合多字段组合键实现分组:字符串拼接需加固定分隔符防歧义;推荐JDK14+ record封装字段,类型安全且自动支持equals/hashCode;须统一处理null值,如用Objects.toString(x, "")兜底。
可以使用
配合自定义的分组键(key)来实现多字段拼接分组,核心在于把多个字段组合成一个唯一、可比较的键对象或字符串。
用字符串拼接构造复合 key
最直观的方式是将多个字段拼接为字符串作为分组依据,注意需保证拼接逻辑具备唯一性和可读性(如加分隔符)。
推荐用固定分隔符(如
或
),避免字段本身含分隔符导致歧义;必要时可做简单转义或使用不可见字符(如
)
示例:按
和
分组
Map> grouped = users.stream()
.collect(Collectors.groupingBy(
u -> u.getDepartment() + "|" + u.getStatus()
));
用记录类(Record)或自定义 Key 类封装多字段
比字符串更类型安全、可读性更好,且天然支持 equals/hashCode,适合复杂场景或后续需进一步处理 key 的情况。
JDK 14+ 推荐用
快速声明不可变 key
字段顺序、null 处理需显式约定(如用
防空)
record DeptStatusKey(String dept, String status) {}
Map> grouped = users.stream()
.collect(Collectors.groupingBy(
u -> new DeptStatusKey(
u.getDepartment(),
Objects.toString(u.getStatus(), "")
)
));
用 Map 或 List 临时组合字段(不推荐用于生产)
可用
或
构造 key,但性能和语义不如 record 或专用类清晰。
作为 key 虽能工作,但因可变性易引发问题(如后续修改 list 内容破坏哈希一致性)
作为 key 效率低、不可序列化、无标准 equals 实现,仅适合原型验证
处理 null 值与空字段的健壮写法
实际数据中字段常为空,直接拼接或构造 record 可能抛
,应统一兜底。
用
替代
若业务上
和空字符串等价,可统一转为空串再拼接
也可在 record 构造时做非空校验并标准化(如
)
Collectors.groupingBy"|""_"\u0000user.departmentuser.statusrecordObjects.toString(x, "")Arrays.asList(f1, f2)Map.of("d", d, "s", s)ListMapNullPointerExceptionObjects.toString(obj, "NULL")obj.toString()nulldept == null ? "" : dept.trim()