Java Stream Collectors 功能全面指南

Java Stream Collectors 功能全面指南

Collectors 是 Java Stream API 中最强大的工具之一,提供了丰富的收集器实现,用于将流中的元素聚合为各种结果。


常用收集器

1. toList() - 收集为列表

List<String> list = stream.collect(Collectors.toList());

用途:将流元素收集到 List
返回ArrayList(非线程安全)


2. toSet() - 收集为集合

Set<Integer> set = stream.collect(Collectors.toSet());

用途:将流元素收集到 Set 中(自动去重)
返回HashSet


3. toMap() - 收集为映射

Map<String, Integer> map = stream.collect(
    Collectors.toMap(
        Function.identity(),  // key 映射
        Function.identity()   // value 映射
    )
);

用途:将流元素收集到 Map
注意:需要处理 key 冲突,可通过第三个参数指定合并策略


4. joining() - 字符串连接

String result = stream.collect(Collectors.joining());
// 带分隔符
String result = stream.collect(Collectors.joining(", "));
// 带分隔符、前缀、后缀
String result = stream.collect(Collectors.joining(", ", "[", "]"));

用途:将字符串流连接成单个字符串


5. counting() - 计数

Long count = stream.collect(Collectors.counting());

用途:统计流中元素数量
也可用stream.count()(更简洁)


6. summarizingInt/Long/Double() - 统计摘要

IntSummaryStatistics stats = stream.collect(
    Collectors.summarizingInt(Integer::intValue)
);
// 获取: count, sum, min, max, average

用途:获取数值流的统计摘要信息


分组与分区

7. groupingBy() - 分组

// 基础分组
Map<String, List<Employee>> grouped = stream.collect(
    Collectors.groupingBy(Employee::getDepartment)
);

// 带下游收集器分组
Map<String, Set<String>> grouped = stream.collect(
    Collectors.groupingBy(
        Employee::getDepartment,
        Collectors.mapping(Employee::getName, Collectors.toSet())
    )
);

用途:按分类函数对元素分组


8. partitioningBy() - 分区

Map<Boolean, List<Integer>> partitioned = stream.collect(
    Collectors.partitioningBy(n -> n % 2 == 0)
);
// 结果: {false=[奇数], true=[偶数]}

用途:按谓词将元素分为两组(true/false)


归约操作

9. reducing() - 归约

// 基础归约
Optional<Integer> sum = stream.collect(
    Collectors.reducing(Integer::sum)
);

// 带初始值归约
Integer sum = stream.collect(
    Collectors.reducing(0, Integer::sum)
);

// 带映射和归约
Optional<Integer> sum = stream.collect(
    Collectors.reducing(
        Employee::getSalary,
        Integer::sum
    )
);

用途:通过二元运算将元素归约为单个值


10. summingInt/Long/Double() - 求和

Integer sum = stream.collect(Collectors.summingInt(Integer::intValue));

用途:对数值流求和


11. averagingInt/Long/Double() - 求平均值

Double average = stream.collect(Collectors.averagingInt(Integer::intValue));

用途:计算数值流的平均值


极值获取

12. maxBy() / minBy() - 最大/最小值

Optional<Integer> max = stream.collect(Collectors.maxBy(Integer::compareTo));
Optional<Integer> min = stream.collect(Collectors.minBy(Integer::compareTo));

用途:获取流中的最大/最小元素


13. collectingAndThen() - 转换结果

List<String> unmodifiableList = stream.collect(
    Collectors.collectingAndThen(
        Collectors.toList(),
        Collections::unmodifiableList
    )
);

用途:收集后对结果进行转换


高级收集器

14. mapping() - 映射收集

Set<String> names = stream.collect(
    Collectors.mapping(
        Employee::getName,
        Collectors.toSet()
    )
);

用途:先映射再收集


15. flatMapping() - 扁平映射收集(Java 9+)

Set<String> allSkills = stream.collect(
    Collectors.flatMapping(
        emp -> emp.getSkills().stream(),
        Collectors.toSet()
    )
);

用途:扁平化映射后收集


16. filtering() - 过滤收集(Java 9+)

List<Employee> senior = stream.collect(
    Collectors.filtering(
        emp -> emp.getAge() > 50,
        Collectors.toList()
    )
);

用途:过滤后再收集


自定义收集器

17. of() - 创建自定义收集器

Collector<String, ?, String> customCollector = Collector.of(
    StringBuilder::new,           // supplier: 创建可变容器
    StringBuilder::append,        // accumulator: 累加元素
    StringBuilder::append,        // combiner: 合并容器
    StringBuilder::toString       // finisher: 转换结果
);

用途:创建完全自定义的收集器


收集器组合

18. 多重收集器

// 同时进行多种收集
Map<String, Object> result = stream.collect(
    Collectors.teeing(
        Collectors.counting(),
        Collectors.summingDouble(Double::doubleValue),
        (count, sum) -> Map.of("count", count, "sum", sum)
    )
);

用途:在一个操作中执行多个收集器(Java 12+)


实用示例

示例 1:员工数据处理

// 按部门分组,收集员工姓名
Map<String, List<String>> departmentEmployees = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getDepartment,
        Collectors.mapping(Employee::getName, Collectors.toList())
    ));

// 按部门统计薪资
Map<String, Double> departmentSalary = employees.stream()
    .collect(Collectors.groupingBy(
        Employee::getDepartment,
        Collectors.summingDouble(Employee::getSalary)
    ));

示例 2:数据转换

// 将列表转换为不可变 Map
Map<Integer, Employee> employeeMap = employees.stream()
    .collect(Collectors.toUnmodifiableMap(
        Employee::getId,
        Function.identity()
    ));

// 字符串拼接
String employeeNames = employees.stream()
    .map(Employee::getName)
    .collect(Collectors.joining(", "));

注意事项

问题解决方案
toList() 返回可变列表使用 toUnmodifiableList() 获取不可变列表
toMap() key 冲突提供合并函数作为第三个参数
并发修改异常使用线程安全的收集器或并行流时注意
空元素处理在收集前过滤或处理空值

版本兼容性

收集器最低版本
基础收集器Java 8
flatMapping, filteringJava 9
teeingJava 12
toUnmodifiableList/Set/MapJava 10

总结

Collectors 提供了强大的数据收集能力:

  • 基础收集toList, toSet, toMap, joining
  • 聚合操作counting, summing, averaging, reducing
  • 分组分区groupingBy, partitioningBy
  • 高级功能collectingAndThen, teeing, 自定义收集器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值