collectors.toset()将流元素转为无序不可重复的set实现去重,collectors.tomap()通过keymapper/valuemapper/mergefunction构建键值映射,需处理重复key与null值。

Collectors.toSet() 和 Collectors.toMap() 是 Java Stream 中两个常用且功能明确的收集器,分别用于将流元素转为 Set 和 Map。它们简洁高效,但使用时需注意约束条件和常见陷阱。
用 toSet() 收集去重元素
该方法把流中所有元素收集到一个 HashSet(无序、不可重复)中,适合快速去重或构建查找集合。
- 不需要手动处理重复逻辑,Stream 自动跳过重复元素(基于
equals()和hashCode()) - 返回的是不可修改的
Set(底层是LinkedHashSet或HashSet,具体实现不保证,也不应依赖) - 如果需要有序结果(如按插入顺序),建议显式用
Collectors.toCollection(LinkedHashSet::new)
示例:
Set
// 结果:{"Alice", "Bob", "Charlie"}(顺序不定)
用 toMap() 构建键值映射
toMap() 有多个重载版本,最常用的是三参数形式:toMap(keyMapper, valueMapper, mergeFunction)
-
keyMapper:定义每个元素如何生成 key(必须非 null,否则抛
NullPointerException) - valueMapper:定义每个元素如何生成 value
- mergeFunction:当 key 冲突时如何合并(比如保留第一个、取最大值、拼接字符串等)
若省略 mergeFunction,遇到重复 key 会直接抛 IllegalStateException —— 这是高频报错点。
示例(处理重复 ID):
Listnew User(1, "Alice"),
new User(2, "Bob"),
new User(1, "Alicia") // ID 重复
);
// 允许覆盖:保留后出现的值
Map
.collect(Collectors.toMap(User::getId, User::getName, (oldVal, newVal) -> newVal));
// 结果:{1="Alicia", 2="Bob"}
toMap() 的常见变体与注意事项
- 双参数版
toMap(k, v)适用于确定无重复 key 的场景(如主键唯一列表),否则运行时报错 - 四参数版可指定
Map实现类,例如:toMap(k, v, merge, TreeMap::new)得到有序 Map - key 或 value 映射函数返回
null会导致NullPointerException,建议提前过滤或判空 - 若想用对象本身作 value,可用
Function.identity(),如toMap(User::getId, Function.identity())
对比与选型建议
- 要去重 + 快速查存在 → 用
toSet() - 要按字段索引查找单个对象(如 ID → User)→ 用
toMap() - 要分组聚合多个对象(如 ID → List
)→ 应用 groupingBy(),不是toMap() - 不确定 key 是否唯一?先
distinct()或加mergeFunction,别硬扛异常
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











