Collectors常用功能有哪些

wen java案例 2

本文目录导读:

Collectors常用功能有哪些

  1. 归集到集合(toList/toSet/toCollection)
  2. 字符串连接(joining)
  3. 分组(groupingBy)
  4. 分区(partitioningBy)
  5. 聚合计算(summarizing / averaging / summing)
  6. 归约(reducing)
  7. 映射(mapping)
  8. 收集到 Map(toMap)
  9. 计数与极值(counting / maxBy / minBy)
  10. 自定义收集(collectingAndThen)
  11. 总结表

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 收集需求,熟练掌握可以大大简化集合操作的代码量。

抱歉,评论功能暂时关闭!