Java里如何使用collect收集流结果_Stream收集技巧解析

collect是Stream API中用于累积元素的终端操作,可转换为集合、字符串或分组数据;常用toList、toSet转集合,joining拼接字符串,groupingBy按条件分组,partitioningBy分区,toMap转Map并处理键冲突,结合下游收集器实现复杂统计,支持并发与不可变集合。

在Java 8引入的Stream API中,collect 是一个非常强大的终端操作,用于将流中的元素累积成我们想要的结果形式,比如集合、字符串、分组数据等。它不像 forEach 那样只是遍历,而是真正“收集”结果,适用于大多数数据处理场景。

1. 基础用法:转为常见集合

最常用的 collect 操作是把流转换为 List、Set 或 Array。

// 转为List

List list = stream.collect(Collectors.toList());

// 转为Set(去重)

Set set = stream.collect(Collectors.toSet());

// 转为数组

String[] array = stream.toArray(String[]::new);

注意:toList 和 toSet 返回的是可变集合,若需不可变集合,建议使用 Collectors.toUnmodifiableList() 等方法(Java 10+)。

2. 使用joining合并字符串

当需要将流中的字符串拼接成一个整体时,joining 非常方便。

// 简单拼接

String names = people.stream().map(Person::getName).collect(Collectors.joining());

// 加分隔符

String joined = stream.collect(Collectors.joining(", "));

// 支持前缀和后缀

String result = stream.collect(Collectors.joining(", ", "[", "]"));

这比手动遍历拼接更简洁,也避免了多余的逗号处理。

3. 分组与分区:groupingBy 和 partitioningBy

实际开发中经常需要按条件分类数据,collect 提供了强大支持。

// 按性别分组

Map> byGender = people.stream()

  .collect(Collectors.groupingBy(Person::getGender));

// 多级分组:先按部门,再按薪资等级

Map>> grouped = people.stream()

  .collect(Collectors.groupingBy(Person::getDept,

    Collectors.grouping

By(p -> p.getSalary() > 8000 ? Level.HIGH : Level.LOW)));

// 分区:true/false 两组

Map> adults = people.stream()

  .collect(Collectors.partitioningBy(p -> p.getAge() >= 18));

4. 自定义收集:使用toMap和下游收集器

将流转换为Map时,需注意key重复问题。

// 正常转Map

Map map = people.stream()

  .collect(Collectors.toMap(Person::getId, p -> p));

// 处理重复key:保留第一个或合并

Map byName = people.stream()

  .collect(Collectors.toMap(Person::getName, p -> p, (e1, e2) -> e1));

第三个参数是冲突解决策略。还可以结合下游收集器实现复杂结构:

// 按部门统计人数

Map countByDept = people.stream()

  .collect(Collectors.groupingBy(Person::getDept, Collectors.counting()));

// 按部门计算平均薪资

Map avgSalary = people.stream()

  .collect(Collectors.groupingBy(Person::getDept, Collectors.averagingDouble(Person::getSalary)));

基本上就这些常用技巧。掌握 collect 的核心在于理解“收集器(Collector)”的组合逻辑。合理使用 groupingBy、mapping、reducing 等下游收集器,能让代码更清晰高效。不复杂但容易忽略细节,比如并发收集(toConcurrentMap)、不可变集合等,根据需求选择合适方式即可。