模块 java.base

接口收集器<T,A,R>

类型参数:
T - 归约操作的输入元素类型
A - 归约操作的可变累积类型(通常隐藏为实现细节)
R - 归约运算的结果类型

public interface Collector<T,A,R>
一个 可变归约操作 将输入元素累积到可变结果容器中,在处理完所有输入元素后,可选择将累积结果转换为最终表示。缩减操作可以顺序执行,也可以并行执行。

可变归约操作的示例包括:将元素累加到 Collection 中;使用 StringBuilder 连接字符串;计算有关元素的摘要信息,例如 sum、min、max 或 average;计算“数据透视表”摘要,例如“卖方的最大值交易”等。类 Collectors 提供了许多常见可变归约的实现。

Collector 由四个函数指定,这些函数协同工作以将条目累积到可变结果容器中,并可选择对结果执行最终转换。他们是:

收集器还有一组特征,例如 Collector.Characteristics.CONCURRENT ,它们提供了缩减实现可以使用的提示以提供更好的性能。

使用收集器的缩减的顺序实现将使用供应商函数创建单个结果容器,并为每个输入元素调用一次累加器函数。并行实现将对输入进行分区,为每个分区创建一个结果容器,将每个分区的内容累积到该分区的一个子结果中,然后使用组合器函数将子结果合并为一个组合结果。

为确保顺序执行和并行执行产生相同的结果,收集器函数必须满足 identity结合性 约束。

恒等约束表示对于任何部分累积的结果,将其与空结果容器组合必须产生等效结果。也就是说,对于任何系列累加器和组合器调用的结果的部分累加结果 aa 必须等同于 combiner.apply(a, supplier.get())

关联性约束表示拆分计算必须产生等效结果。也就是说,对于任何输入元素 t1t2,下面计算中的结果 r1r2 必须相等:


   A a1 = supplier.get();
   accumulator.accept(a1, t1);
   accumulator.accept(a1, t2);
   R r1 = finisher.apply(a1); // result without splitting

   A a2 = supplier.get();
   accumulator.accept(a2, t1);
   A a3 = supplier.get();
   accumulator.accept(a3, t2);
   R r2 = finisher.apply(combiner.apply(a2, a3)); // result with splitting
  

对于不具有 UNORDERED 特性的收集器,两个累加结果 a1a2 等价于 finisher.apply(a1).equals(finisher.apply(a2)) 。对于无序收集器,等价性被放宽以允许与顺序差异相关的非等式。 (例如,一个将元素累积到 List 的无序收集器会认为两个列表等价,如果它们包含相同的元素,忽略顺序。)

基于 Collector 实现缩减的库,例如 Stream.collect(Collector) ,必须遵守以下约束:

  • 传递给累加器函数的第一个参数、传递给组合器函数的两个参数以及传递给完成器函数的参数必须是先前调用结果提供者、累加器或组合器函数的结果。
  • 实现不应该对任何结果提供者、累加器或组合器函数的结果做任何事情,除非将它们再次传递给累加器、组合器或完成器函数,或者将它们返回给归约操作的调用者。
  • 如果将结果传递给组合器或整理器函数,并且该函数未返回相同的对象,则永远不会再次使用它。
  • 一旦将结果传递给组合器或整理器函数,它就不会再传递给累加器函数。
  • 对于非并发收集器,从结果提供者、累加器或组合器函数返回的任何结果都必须是串行线程限制的。这使得收集可以并行进行,而无需Collector 实现任何额外的同步。缩减实现必须管理输入被正确分区,分区被隔离处理,并且只有在累积完成后才发生组合。
  • 对于并发收集器,一个实现可以自由(但不是必须)并发地实现缩减。并发缩减是从多个线程同时调用累加器函数,使用相同的可同时修改的结果容器,而不是在累加期间保持结果隔离。只有当收集器具有 Collector.Characteristics.UNORDERED 特征或原始数据是无序的时,才应应用并发减少。

除了 Collectors 中的预定义实现之外,静态工厂方法 of(Supplier, BiConsumer, BinaryOperator, Characteristics...) 可用于构造收集器。例如,您可以创建一个收集器,将小部件累积到一个 TreeSet 中:


   Collector<Widget, ?, TreeSet<Widget>> intoSet =
     Collector.of(TreeSet::new, TreeSet::add,
           (left, right) -> { left.addAll(right); return left; });
  
(此行为也由预定义收集器 Collectors.toCollection(Supplier) 实现)。
API 注意:
使用 Collector 执行缩减操作应产生等同于:

   A container = collector.supplier().get();
   for (T t : data)
     collector.accumulator().accept(container, t);
   return collector.finisher().apply(container);
  
的结果

然而,该库可以自由地对输入进行分区,对分区进行归约,然后使用组合器功能将部分结果组合起来,以实现并行归约。 (根据具体的归约操作,这可能表现得更好或更差,具体取决于累加器和组合器功能的相对成本。)

收集器设计为 composedCollectors 中的许多方法都是采用收集器并生成新收集器的函数。例如,给定以下收集器计算员工流的工资总和:


   Collector<Employee, ?, Integer> summingSalaries
     = Collectors.summingInt(Employee::getSalary))
  
如果我们想创建一个收集器来按部门列出工资总和,我们可以使用 Collectors.groupingBy(Function, Collector) 重用“工资总和”逻辑:

   Collector<Employee, ?, Map<Department, Integer>> summingSalariesByDept
     = Collectors.groupingBy(Employee::getDepartment, summingSalaries);
  
自从:
1.8
参见:
  • 方法详情

    • supplier

      Supplier <A > supplier()
      创建并返回新的可变结果容器的函数。
      返回:
      返回一个新的可变结果容器的函数
    • accumulator

      BiConsumer <A ,T > accumulator()
      将值折叠到可变结果容器中的函数。
      返回:
      将值折叠到可变结果容器中的函数
    • combiner

      BinaryOperator <A > combiner()
      接受两个部分结果并将它们合并的函数。组合器函数可以将状态从一个参数折叠到另一个参数并返回它,或者可以返回一个新的结果容器。
      返回:
      将两个部分结果组合成组合结果的函数
    • finisher

      Function <A ,R > finisher()
      执行从中间累积类型 A 到最终结果类型 R 的最终转换。

      如果设置了特征 IDENTITY_FINISH,则可以假定此函数是一个恒等变换,具有从 AR 的未经检查的转换。

      返回:
      将中间结果转换为最终结果的函数
    • characteristics

      Set <Collector.Characteristics > characteristics()
      返回 Collector.CharacteristicsSet 指示此收集器的特征。这个集合应该是不可变的。
      返回:
      一组不可变的收集器特征
    • of

      static <T, R> Collector <T,R,R> of(Supplier <R> supplier, BiConsumer <R,T> accumulator, BinaryOperator <R> combiner, Collector.Characteristics ... characteristics)
      返回由给定的 supplieraccumulatorcombiner 函数描述的新 Collector。生成的 Collector 具有 Collector.Characteristics.IDENTITY_FINISH 特性。
      类型参数:
      T - 新收集器的输入元素类型
      R - 新收集器的中间累积结果类型和最终结果
      参数:
      supplier - 新收集器的供应商功能
      accumulator - 新收集器的累加器函数
      combiner - 新收集器的组合器功能
      characteristics - 新收集器的收集器特性
      返回:
      新的Collector
      抛出:
      NullPointerException - 如果任何参数为空
    • of

      static <T, A, R> Collector <T,A,R> of(Supplier <A> supplier, BiConsumer <A,T> accumulator, BinaryOperator <A> combiner, Function <A,R> finisher, Collector.Characteristics ... characteristics)
      返回由给定的 supplieraccumulatorcombinerfinisher 函数描述的新 Collector
      类型参数:
      T - 新收集器的输入元素类型
      A - 新收集器的中间累积类型
      R - 新收集器的最终结果类型
      参数:
      supplier - 新收集器的供应商功能
      accumulator - 新收集器的累加器函数
      combiner - 新收集器的组合器功能
      finisher - 新收集器的整理函数
      characteristics - 新收集器的收集器特性
      返回:
      新的Collector
      抛出:
      NullPointerException - 如果任何参数为空