本文目录导读:

- 归集到集合(toList/toSet/toCollection)
- 字符串连接(joining)
- 分组(groupingBy)
- 分区(partitioningBy)
- 聚合计算(summarizing / averaging / summing)
- 归约(reducing)
- 映射(mapping)
- 收集到 Map(toMap)
- 计数与极值(counting / maxBy / minBy)
- 自定义收集(collectingAndThen)
- 总结表
Java 8 中引入的 Collectors 是一个非常强大的工具类,主要用于将 Stream 中的元素累积到各种容器(如 List、Set、Map)中,或者进行各种归约操作(如求和、分组、连接字符串)。
以下是 Collectors 最常用的十大功能分类及代码示例:
归集到集合(toList/toSet/toCollection)
将流中的数据收集到常见的集合中。
import java.util.stream.Collectors; import java.util.*; // toList: 默认使用 ArrayList List<String> list = stream.collect(Collectors.toList()); // toSet: 去重,默认使用 HashSet Set<String> set = stream.collect(Collectors.toSet()); // toCollection: 指定具体的集合类型(如 TreeSet, LinkedList) TreeSet<String> treeSet = stream.collect(Collectors.toCollection(TreeSet::new));
字符串连接(joining)
将流中的元素(通常是字符串)连接成一个字符串,可以指定分隔符、前缀和后缀。
List<String> words = Arrays.asList("Hello", "World", "Java");
// 简单连接: "HelloWorldJava"
String s1 = words.stream().collect(Collectors.joining());
// 带分隔符: "Hello, World, Java"
String s2 = words.stream().collect(Collectors.joining(", "));
// 带分隔符、前缀、后缀: "[Hello, World, Java]"
String s3 = words.stream().collect(Collectors.joining(", ", "[", "]"));
分组(groupingBy)
类似 SQL 中的 GROUP BY,根据属性将元素分组,返回 Map<K, List<V>>。
// 假设有一个 Person 类,包含 age 和 name
List<Person> people = ...;
// 按年龄分组: Map<Integer, List<Person>>
Map<Integer, List<Person>> byAge = people.stream()
.collect(Collectors.groupingBy(Person::getAge));
// 分组后计数: Map<Integer, Long> (每个年龄有多少人)
Map<Integer, Long> ageCount = people.stream()
.collect(Collectors.groupingBy(Person::getAge, Collectors.counting()));
// 分组后映射: 按年龄分组,只取名字: Map<Integer, List<String>>
Map<Integer, List<String>> namesByAge = people.stream()
.collect(Collectors.groupingBy(Person::getAge,
Collectors.mapping(Person::getName, Collectors.toList())));
分区(partitioningBy)
是 groupingBy 的特殊情况,根据 boolean 条件将数据分为两组(true 和 false)。
// 按年龄是否大于18分区
Map<Boolean, List<Person>> partitioned = people.stream()
.collect(Collectors.partitioningBy(p -> p.getAge() >= 18));
// 获取成年人的列表
List<Person> adults = partitioned.get(true);
聚合计算(summarizing / averaging / summing)
用于计算数值型属性的统计量。
// 求总和: int/ long/ double
int totalAge = people.stream().collect(Collectors.summingInt(Person::getAge));
// 求平均值: double
double avgAge = people.stream().collect(Collectors.averagingInt(Person::getAge));
// 一次性获取 计数、总和、最小、最大、平均: IntSummaryStatistics
IntSummaryStatistics stats = people.stream()
.collect(Collectors.summarizingInt(Person::getAge));
// stats.getCount(); stats.getSum(); stats.getMin(); stats.getMax(); stats.getAverage();
归约(reducing)
这是 Collectors 中最底层、最通用的归约操作,其他如 summing 等通常基于它实现。
// 求所有年龄的总和
Optional<Integer> total = people.stream()
.map(Person::getAge)
.collect(Collectors.reducing((a, b) -> a + b));
// 带初始值的归约
Integer totalWithInit = people.stream()
.map(Person::getAge)
.collect(Collectors.reducing(0, (a, b) -> a + b));
映射(mapping)
用于对元素进行转换后再收集,常配合其他 Collector 使用。
// 将所有 Person 的名字转为大写并收集到 List
List<String> upperNames = people.stream()
.collect(Collectors.mapping(
p -> p.getName().toUpperCase(),
Collectors.toList()
));
收集到 Map(toMap)
将 Stream 转换为 Map,需要指定 Key 和 Value 的提取函数。需要小心 key 冲突。
// 将 Person 对象的 id 作为 key,name 作为 value
Map<Integer, String> idToName = people.stream()
.collect(Collectors.toMap(
Person::getId, // key 提取
Person::getName // value 提取
));
// 处理 key 冲突: 如果两个 Person id 相同,保留第一个
Map<Integer, Person> idToPerson = people.stream()
.collect(Collectors.toMap(
Person::getId,
Function.identity(), // 元素本身作为value
(existing, replacement) -> existing // 冲突时保留已有
));
计数与极值(counting / maxBy / minBy)
// 计数: long
long count = people.stream().collect(Collectors.counting());
// 找年龄最大的人: Optional<Person>
Optional<Person> oldest = people.stream()
.collect(Collectors.maxBy(Comparator.comparingInt(Person::getAge)));
// 找年龄最小的人
Optional<Person> youngest = people.stream()
.collect(Collectors.minBy(Comparator.comparingInt(Person::getAge)));
自定义收集(collectingAndThen)
在收集完成后,对结果再做一次额外处理。
// 收集为 List,然后转为不可变集合
List<String> unmodifiableList = words.stream()
.collect(Collectors.collectingAndThen(
Collectors.toList(), // 先收集成 List
Collections::unmodifiableList // 再包装为不可变
));
// 分组后统计每组数量,并返回一个不可变 Map
Map<Integer, Long> immutableCount = people.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(Person::getAge, Collectors.counting()),
Collections::unmodifiableMap
));
总结表
| 功能 | 方法名 | 典型返回类型 |
|---|---|---|
| 转 List | toList() |
List<T> |
| 转 Set | toSet() |
Set<T> |
| 转指定类型 | toCollection() |
Collection<T> |
| 字符串连接 | joining() |
String |
| 分组 | groupingBy() |
Map<K, List<V>> |
| 分区 | partitioningBy() |
Map<Boolean, List<V>> |
| 数值求和 | summingInt/Long/Double() |
int/long/double |
| 数值统计 | summarizingInt() |
IntSummaryStatistics |
| 归约 | reducing() |
Optional<T> 或 T |
| 映射 | mapping() |
取决于下游收集器 |
| 转 Map | toMap() |
Map<K, V> |
| 计数 | counting() |
Long |
| 最大/最小 | maxBy()/minBy() |
Optional<T> |
| 后处理 | collectingAndThen() |
取决于处理函数 |
这些功能基本覆盖了日常开发中 90% 以上的 Stream 收集需求,熟练掌握可以大大简化集合操作的代码量。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播