Java Stream Collectors 用法

Java Stream 的 Collectors 类提供了大量用于将流中元素收集到不同数据结构或执行聚合操作的工具方法。以下是其主要用法和高级功能:

1. 基础收集方法

toList()、toSet()、toMap()

这些是最常用的收集方法,分别将流元素收集到 List、Set 和 Map 中:

List<String> list = stream.collect(Collectors.toList()); Set<String> set = stream.collect(Collectors.toSet()); Map<String, Integer> map = stream.collect(Collectors.toMap(String::toLowerCase, String::length));

toMap 用于将流中的元素转换为 Map。当存在重复键时,需要提供合并函数。例如:

Map<String, String> idToName = people.stream()

.collect(Collectors.toMap(Person::getId, Person::getName,

(existing, replacement) -> replacement));

此外,还可以使用 toUnmodifiableMap(Java 10+)创建不可变的 Map:

Map<String, String> unmodifiableMap = people.stream()

.collect(Collectors.toUnmodifiableMap(Person::getId, Person::getName));

toCollection() 允许指定具体的集合类型:

List<String> list = stream.collect(Collectors.toCollection(ArrayList::new)); Set<String> set = stream.collect(Collectors.toCollection(HashSet::new));

2. 分组与分区

groupingBy()进行分组并结合下游收集器

根据指定条件对元素进行分组,返回 Map:

Map<String, List<Person>> peopleByCity = people.stream() .collect(Collectors.groupingBy(Person::getCity));

可以结合下游收集器进行统计:

例如,按条件分组并统计每组数量:

Map<String, Long> countByCity = people.stream() .collect(Collectors.groupingBy(Person::getCity, Collectors.counting()));

这种用法可以轻松实现类似 SQL 中 GROUP BY 的功能,并配合 counting()、summingInt() 等下游收集器进行统计操作。

groupingBy()进行多级分组

可以通过嵌套使用 groupingBy 实现多级分组。例如,先按部门分组,再按职位分组:

Map<String, Map<String, List<Employee>>> byDeptAndPosition = employees.stream()

.collect(Collectors.groupingBy(Employee::getDepartment, Collectors.groupingBy(Employee::getPosition)));

partitioningBy()进行二元分类

根据布尔条件将元素分为两组:

Map<Boolean, List<Person>> partitioned = people.stream() .collect(Collectors.partitioningBy(p -> p.getAge() >= 18));

也可以结合下游收集器,如统计每个分区的元素数量:

Map<Boolean, Long> counts = numbers.stream()

.collect(Collectors.partitioningBy(n -> n % 2 == 0, Collectors.counting()));

3. 聚合与统计

counting() 统计元素数量:

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

summingInt()、summingLong()、summingDouble()

对数值字段进行求和:

int total = people.stream().collect(Collectors.summingInt(Person::getAge));

averagingInt()、averagingLong()、averagingDouble()

计算平均值:

double average = people.stream().collect(Collectors.averagingInt(Person::getAge));

summarizingInt() 等

提供全面的统计信息(计数、总和、平均值、最大值、最小值):

IntSummaryStatistics stats = people.stream() .collect(Collectors.summarizingInt(Person::getAge));

4. 字符串连接

joining()

将流中的字符串元素连接成一个字符串:

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

5. reducing 实现归约操作

reducing()

执行自定义的归约操作:

Optional<Integer> sum = numbers.stream().collect(Collectors.reducing(Integer::sum));

reducing 用于对流中的元素进行归约操作,例如求和或查找最大值:

// 求和

int sum = numbers.stream()

.collect(Collectors.reducing(0, Integer::sum));

// 查找最长字符串

Optional<String> longest = words.stream()

.collect(Collectors.reducing((a, b) -> a.length() > b.length() ? a : b));

6. 后处理

collectingAndThen()

在收集完成后对结果进行处理:

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

7. 并发收集

groupingByConcurrent()

支持并发分组操作:

Map<String, List<Person>> concurrentGrouped = people.stream() .collect(Collectors.groupingByConcurrent(Person::getCity));

8. 统计信息收集

Collectors 提供了多种用于统计的收集器,如 summarizingInt、summarizingDouble 等,可以方便地计算总和、平均值、最大值、最小值等:

IntSummaryStatistics stats = students.stream()

.collect(Collectors.summarizingInt(Student::getScore));

9. 自定义收集器

可以通过 Collector 接口创建自定义收集器,实现特定的收集逻辑。

这些功能使得 Collectors 成为 Java Stream API 中处理数据聚合、分组和转换的强大工具。

相关推荐
龙腾-虎跃1 分钟前
AI-Vue3-python-flask-Blog 全栈博客项目深度解析:从零搭建你的 AI 博客
人工智能·python·flask
余槐i2 分钟前
无慢查询 RT 却飙升:cProfile 定位 FastAPI 事件循环阻塞
后端·python·性能优化·fastapi·asyncio
Xiu Yan13 分钟前
Python 数据分析:数据分析步骤
开发语言·python·数据分析
vilya13 分钟前
把 Python 塞进 APK:Chaquopy 打包实践
android·python
黑妹天下第一乖21 分钟前
小智改造实战解读-用kokoro-onnx替换云端 TTS 的完整记录
大数据·开发语言·人工智能·python·交互
郑州光合科技余经理22 分钟前
本地生活平台搭建:跨业态用户标识怎么贯通
java·开发语言·前端·后端·uni-app·php·ai编程
木头科技29 分钟前
【AI 工程化第八篇】Spring AI 多模型路由实战:DeepSeek、通义、Kimi、OpenAI 如何统一接入和自动切换
java·人工智能·spring
深盾科技_Virbox31 分钟前
云端与本地并行交付,软件许可管理如何实现统一运营?
java·大数据·开发语言·安全
thefool11226632 分钟前
多线程 3
java
CoderYanger38 分钟前
A.每日一题:856. 括号的分数
java·程序人生·算法·leetcode·面试·职场和发展·学习方法