Java 中的 Collectors 类 2025 年 5 月 29 日 | 阅读 10 分钟
Collectors 是一个 final 类,它继承自 Object 类。它提供了规约(reduction)操作,例如将元素累积到集合中,根据各种标准对元素进行汇总等。
该类属于 java.util.stream 包。这意味着 Collectors 类是 Java 8 中引入的 Stream API 的一部分,它以函数式编程风格提供了对集合执行聚合操作的功能。
Collectors 类的目的 Collectors 类的主要目的是充当 Collector 实现的工厂,这些实现对于常见的规约操作非常有用。 它允许我们将流转换为各种集合类型(如 List、Set 或 Map),执行分组、分区、汇总,甚至简单的字符串连接。
Java Collectors 类方法 Java Collectors 类提供了各种方法来处理元素。
方法 描述 public static <T> Collector<T,?,Double> averagingDouble(ToDoubleFunction<? super T> mapper) 它返回一个 Collector,该 Collector 对应用于输入元素的双精度值函数执行算术平均。如果不存在元素,则结果为 0。当您想从对象流中计算平均值(例如平均工资或平均评分)时,此方法非常有用。 public static <T> Collector<T,?,T> reducing(T identity, BinaryOperator<T> op) 它返回一个 Collector,该 Collector 使用提供的标识符,在指定的 BinaryOperator 下对输入元素执行规约。标识符值用作起点,然后累积应用规约运算符来组合所有元素。 public static <T> Collector<T,?,Optional<T>> reducing(BinaryOperator<T> op) 它返回一个 Collector,该 Collector 在指定的 BinaryOperator 下对输入元素执行规约。结果描述为 Optional<T>。此版本不需要标识符值,并返回一个 Optional,如果流为空,则该 Optional 为空。 public static <T,U> Collector<T,?,U> reducing(U identity, Function<? super T,? extends U> mapper, BinaryOperator<U> op) 它返回一个 Collector,该 Collector 在指定的映射函数和 BinaryOperator 下对输入元素执行规约。它是 reducing(Object, BinaryOperator) 的泛化,允许在规约之前对元素进行转换。当您需要转换元素后再进行规约时,它特别有用。 public static <T,K> Collector<T,?,Map<K,List<T>>> groupingBy(Function<? super T,? extends K> classifier) 它返回一个 Collector,该 Collector 根据分类函数对输入元素 T 进行“分组”操作,并将结果存储在 Map 中。这是流中基于属性(例如按城市分组人或按部门分组员工)对元素进行分组的最常用方法之一。 public static <T,K,A,D> Collector<T,?,Map<K,D>> groupingBy(Function<? super T,? extends K> classifier, Collector<? Super T,A,D> downstream) 它返回一个 Collector,该 Collector 根据分类函数对输入元素 T 进行级联“分组”操作,然后使用指定的下游 Collector 对与给定键关联的值执行规约操作。它支持复杂的多级分组和聚合,例如按类别分组和汇总数量。 public static <T, K, D, A, M extends Map<K, D>> Collector<T,?, M> groupingBy(Function<? super T,? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream) 它返回一个 Collector,该 Collector 根据分类函数对输入元素 T 进行级联“分组”操作,然后使用指定的下游 Collector 对与给定键关联的值执行规约操作。Collector 生成的 Map 使用提供的工厂函数创建。此方法允许完全控制使用的 Map 类型(例如 LinkedHashMap、TreeMap)以及如何处理分组值。 public static <T,K> Collector<T,?,ConcurrentMap<K,List<T>>> groupingByConcurrent(Function<? super T,? extends K> classifier) 它返回一个并发 Collector,该 Collector 根据分类函数对输入元素 T 进行“分组”操作。它专为并行流处理而设计,并使用 ConcurrentMap 生成线程安全的组。 public static <T,K,A,D> Collector<T,?,ConcurrentMap<K,D>> groupingByConcurrent(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream) 它返回一个并发 Collector,该 Collector 根据分类函数对输入元素 T 进行级联“分组”操作,然后使用指定的下游 Collector 对与给定键关联的值执行规约操作。 public static <T,K,A,D,M extends ConcurrentMap<K,D>> Collector<T,?,M> groupingByConcurrent(Function<? super T,? extends K> classifier, Supplier<M> mapFactory, Collector<? super T,A,D> downstream) 它返回一个并发 Collector,该 Collector 根据分类函数对输入元素 T 进行级联“分组”操作,然后使用指定的下游 Collector 对与给定键关联的值执行规约操作。Collector 生成的 ConcurrentMap 使用提供的工厂函数创建。 public static <T> Collector<T,?,Map<Boolean,List<T>>> partitioningBy(Predicate<? super T> predicate) 它返回一个 Collector,该 Collector 根据 Predicate 对输入元素进行分区,并将它们组织到 Map<Boolean, List<T>> 中。对于返回的 Map,对其类型、可变性、可序列化性或线程安全性没有保证。 public static <T,D,A> Collector<T,?,Map<Boolean,D>> partitioningBy(Predicate<? super T> predicate, Collector<? Super T,A,D> downstream) 它返回一个 Collector,该 Collector 根据 Predicate 对输入元素进行分区,根据另一个 Collector 对每个分区中的值进行规约,并将它们组织到 Map<Boolean, D> 中,其中值是下游规约的结果。 public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) 它返回一个 Collector,该 Collector 将输入元素累积到 Map 中,该 Map 的键和值是通过对输入元素应用提供的映射函数生成的。如果遇到重复键,除非提供了合并函数,否则将抛出 IllegalStateException。 public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction) 它返回一个 Collector,该 Collector 将输入元素累积到 Map 中,该 Map 的键和值是通过对输入元素应用提供的映射函数生成的。 public static <T,K,U,M extends Map<K,U>> Collector<T,?,M> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier) 它返回一个 Collector,该 Collector 将输入元素累积到 Map 中,该 Map 的键和值是通过对输入元素应用提供的映射函数生成的。 public static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) 它返回一个并发 Collector,该 Collector 将输入元素累积到 ConcurrentMap 中,该 ConcurrentMap 的键和值是通过对输入元素应用提供的映射函数生成的。 public static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction) 它返回一个并发 Collector,该 Collector 将输入元素累积到 ConcurrentMap 中,该 ConcurrentMap 的键和值是通过对输入元素应用提供的映射函数生成的。 public static <T,K,U,M extends ConcurrentMap<K,U>> Collector<T,?,M> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier) 它返回一个并发 Collector,该 Collector 将输入元素累积到 ConcurrentMap 中,该 ConcurrentMap 的键和值是通过对输入元素应用提供的映射函数生成的。对于高级并行操作,它具有高度的可定制性。 public static <T> Collector<T,?,IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) 它返回一个 Collector,该 Collector 对每个输入元素应用一个 int 生成的映射函数,并返回生成的值的摘要统计信息。 public static <T> Collector<T,?,LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) 它返回一个 Collector,该 Collector 对每个输入元素应用一个 long 生成的映射函数,并返回生成的值的摘要统计信息。一次性包括计数、总和、最小值、最大值和平均值。 public static <T> Collector<T,?,DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) 它返回一个 Collector,该 Collector 对每个输入元素应用一个 double 生成的映射函数,并返回生成的值的摘要统计信息。在一次操作中收集平均值、计数、最大值、最小值和总和非常有效。 public static <T> Collector<T,?,List<T>> toList() 它返回一个 Collector,该 Collector 将输入元素累积到新的 List 中。这是最常用的 Collectors 之一。 public static <T> Collector<T,?,Set<T>> toSet() 它返回一个 Collector,该 Collector 将输入元素累积到 Set 中,并在此过程中删除重复项。 public static <T> Collector<T,?,String> joining() 它返回一个 Collector,该 Collector 将输入元素按遇到顺序连接成一个单一的 String。仅适用于 CharSequence 流或 toString() 有意义的情况。 public static <T> Collector<T,?,String> joining(CharSequence delimiter) 它返回一个 Collector,该 Collector 使用给定的分隔符连接 CharSequence 元素。对于构建逗号分隔的字符串很有用。 public static <T> Collector<T,?,String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) 它通过允许可选的前缀和后缀来扩展 joining(delimiter)。对于构建类似 JSON 或 SQL 的字符串结构很有用。 public static <T> Collector<T,?,Long> counting() 它返回一个 Collector,该 Collector 计算输入元素的数量。通常用于简单的统计。
示例 示例 1:将数据作为 List 获取 输出
[25000.0, 30000.0, 28000.0, 28000.0, 90000.0] 说明
我们使用 map() 函数提取每个产品的价格。然后,我们使用 Collectors.toList() 将这些价格收集到 List<Float> 中。
时间复杂度: O(n),其中 n 是列表中产品的数量。每个产品都处理一次。
示例 2:将数据作为 Set 转换 输出
[25000.0, 30000.0, 28000.0, 90000.0] 说明
在这里,我们使用 Collectors.toSet() 而不是 toList() 来删除重复的价格。由于 Set 不允许重复,因此只剩下唯一的价格。
时间复杂度: O(n),用于流式传输和插入到 HashSet。
示例 3:使用 sum() 方法 输出
Sum of prices: 201000.0
Sum of id's: 15
说明
我们使用 Collectors.summingDouble() 来对价格求和,使用 summingInt() 来对 ID 求和。这些是专门的 Collectors,有助于聚合数值数据。
时间复杂度: O(n),因为每个元素都被遍历一次以计算总和。
示例 4:获取产品平均价格 输出
Average price is: 40200.0 说明
averagingDouble() Collector 首先对所有元素求和,然后除以计数,从而计算出价格的平均值。
时间复杂度: O(n),因为每个产品都被访问一次以计算总和并计数。
示例 5:计数元素 输出
说明
Collectors.counting() 是一个终止 Collector,它只计算流中元素的数量。
时间复杂度: O(n),其中 n 是产品的总数。
使用 Collectors 的优点 常见操作的代码简洁易读。 通过内部迭代和单次计算提高性能。 使用 groupingByConcurrent() 和 toConcurrentMap() 轻松与并行流集成。 高度可定制,用于高级数据处理。 Java Collectors 选择题 1. Java 中的 Collectors 类有哪些有效用途?
执行数学计算 对流执行规约操作 处理流中的异常 打开 Java 中的文件 显示答案 工作区
答案:2)
解释: Collectors 类提供了各种静态方法来执行规约操作,例如 toList()、groupingBy() 和 averagingDouble()。
2. Collectors.toList() 方法返回什么?
一个数组 一个流 包含流元素的 List 包含流元素的 Set 显示答案 工作区
答案:3)
解释: Collectors.toList() 将流的元素收集到一个 List 中。
3. 哪个 Collectors 方法用于按分类函数对元素进行分组?
toMap() groupingBy() partitioningBy() averagingDouble() 显示答案 工作区
答案:2)
解释: Collectors.groupingBy() 用于按分类函数对流元素进行分组并将它们收集到 Map 中。
4. Collectors.averagingDouble() 返回什么?
一个双精度值流 一个整数平均值 一个计算双精度值平均值的 Collector 一个双精度平均值的 Map 显示答案 工作区
答案:3)
解释: 此方法返回一个 Collector,该 Collector 计算流元素的双精度值的平均值。
5. partitioningBy() 返回什么?
一个分区列表 一个 Map<Boolean, List<T>> 一个 Map<Integer, List<T>> 一个单一的布尔结果 显示答案 工作区
答案:2)
解释: Collectors.partitioningBy() 根据 Predicate 将元素分成两组,并将它们作为 Map<Boolean, List<T>> 返回。