java中collect方法通过collectors可将stream收集为set或map:set用toset()或tocollection指定实现类(如linkedhashset保持顺序、treeset自然排序);map用tomap()需提供键值映射器及冲突处理函数,groupingby适用于分组,toconcurrentmap支持并发。

Java 中 collect 方法通过 Collectors 工具类,可以方便地将流(Stream)收集为 Set 或 Map。关键在于选择合适的收集器,并注意集合的特性(如 Set 不允许重复、Map 需要键唯一)。
收集为 Set:用 toSet() 或 toCollection(HashSet::new)
Collectors.toSet() 是最常用的方式,它返回一个不保证顺序、无重复的 Set(底层通常是 HashSet)。但要注意:它不保证线程安全,也不保留插入顺序。
如果需要指定实现类(比如明确要用 LinkedHashSet 保持插入顺序),可用 toCollection():
-
stream.collect(Collectors.toSet())→ 返回任意Set实现(通常为HashSet) -
stream.collect(Collectors.toCollection(LinkedHashSet::new))→ 保持插入顺序 -
stream.collect(Collectors.toCollection(TreeSet::new))→ 自然排序(元素需实现Comparable或传入Comparator)
收集为 Map:用 toMap(),注意键冲突和空值
Collectors.toMap() 需要提供三个函数:键映射器(keyMapper)、值映射器(valueMapper),以及可选的合并函数(用于处理键重复)。
基础用法(假设 Person 有 id 和 name 字段):
list.stream().collect(Collectors.toMap(Person::getId, Person::getName))- 若出现重复
id,会抛出IllegalStateException - 解决冲突:加第三个参数,如
(oldVal, newVal) -> oldVal(保留旧值)或(oldVal, newVal) -> newVal(覆盖为新值) - 若键或值可能为
null,需注意HashMap允许一个null键,但toMap默认使用HashMap,遇到多个null键仍会报错
更灵活的 Map 收集:groupingBy 和 toConcurrentMap
当需要按条件分组(如按年龄归类所有人),Collectors.groupingBy() 更直观:
-
list.stream().collect(Collectors.groupingBy(Person::getAge))→ 返回Map<integer list>></integer> - 可叠加下游收集器,例如
groupingBy(Person::getAge, Collectors.counting())→ 统计每组人数
多线程环境下,可用 toConcurrentMap() 替代 toMap(),它返回 ConcurrentMap(如 ConcurrentHashMap),支持并发写入。
常见陷阱提醒
收集到 Set 时,对象必须正确重写 equals() 和 hashCode(),否则去重失效;收集到 Map 时,键映射结果若为 null 会直接抛 NullPointerException(JDK 12+ 对部分场景做了优化,但仍建议提前判空)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











