Java中用collect转流为Map需调用Collectors.toMap(),指定键值提取逻辑及键冲突合并策略,默认返回HashMap,可选TreeMap或ConcurrentHashMap,且不支持null键或值。

Java 中用 collect 将流转为 Map,核心是调用 Collectors.toMap(),并明确指定键、值生成逻辑,同时处理键冲突问题。
基础用法:指定 key 和 value
最常见场景是把对象列表按某个字段作为 key,整个对象或某字段作为 value:
-
toMap(keyMapper, valueMapper):两个函数式参数,分别提取 key 和 value - 要求 key 不能重复,否则运行时报
IllegalStateException
示例:
List<User> users = Arrays.asList(new User("u1", "Alice"), new User("u2", "Bob"));Map<String, String> idToName = users.stream()
.collect(Collectors.toMap(User::getId, User::getName));
// 结果:{"u1"="Alice", "u2"="Bob"}
处理键冲突:提供合并策略
当流中多个元素生成相同 key 时,必须传入第三个参数 mergeFunction 决定如何合并 value:
立即学习“Java免费学习笔记(深入)”;
- 常用策略:保留第一个(
(v1, v2) -> v1)、保留最后一个((v1, v2) -> v2)、合并成集合等 - 该函数接收旧值和新值,返回最终要存入 Map 的值
示例(相同 ID 多个用户,只保留最新姓名):
Map<String, String> idToLatestName = users.stream().collect(Collectors.toMap(User::getId, User::getName, (old, neo) -> neo));
指定 Map 类型和并发支持
默认返回 HashMap,如需其他实现(如 TreeMap 或线程安全的 ConcurrentHashMap),使用四参数重载:
toMap(keyMapper, valueMapper, mergeFn, mapSupplier)-
mapSupplier是一个 Supplier,例如TreeMap::new或ConcurrentHashMap::new
示例(按 ID 字典序排序的 Map):
Map<String, User> sortedMap = users.stream().collect(Collectors.toMap(User::getId, Function.identity(),
(u1, u2) -> u1, TreeMap::new));
注意空值和 null 安全
toMap 不接受 null 键或 null 值(除非自定义 Map 实现):
- 若 keyMapper 或 valueMapper 可能返回
null,需提前过滤或映射为非空值 - 常见做法:
.filter(u -> u.getId() != null && u.getName() != null) - 也可用
Collectors.collectingAndThen包装,但更推荐前置校验
不复杂但容易忽略。


















