- 类型参数:
T- 归约操作的输入元素类型A- 归约操作的可变累积类型(通常隐藏为实现细节)R- 归约运算的结果类型
可变归约操作的示例包括:将元素累加到 Collection 中;使用 StringBuilder 连接字符串;计算有关元素的摘要信息,例如 sum、min、max 或 average;计算“数据透视表”摘要,例如“卖方的最大值交易”等。类 Collectors 提供了许多常见可变归约的实现。
Collector 由四个函数指定,这些函数协同工作以将条目累积到可变结果容器中,并可选择对结果执行最终转换。他们是:
- 创建一个新的结果容器(
supplier()) - 将新数据元素合并到结果容器中 (
accumulator()) - 将两个结果容器合并为一个 (
combiner()) - 对容器执行可选的最终转换 (
finisher())
收集器还有一组特征,例如 Collector.Characteristics.CONCURRENT ,它们提供了缩减实现可以使用的提示以提供更好的性能。
使用收集器的缩减的顺序实现将使用供应商函数创建单个结果容器,并为每个输入元素调用一次累加器函数。并行实现将对输入进行分区,为每个分区创建一个结果容器,将每个分区的内容累积到该分区的一个子结果中,然后使用组合器函数将子结果合并为一个组合结果。
为确保顺序执行和并行执行产生相同的结果,收集器函数必须满足 identity 和 结合性 约束。
恒等约束表示对于任何部分累积的结果,将其与空结果容器组合必须产生等效结果。也就是说,对于任何系列累加器和组合器调用的结果的部分累加结果 a,a 必须等同于 combiner.apply(a, supplier.get())。
关联性约束表示拆分计算必须产生等效结果。也就是说,对于任何输入元素 t1 和 t2,下面计算中的结果 r1 和 r2 必须相等:
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 特性的收集器,两个累加结果 a1 和 a2 等价于 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);然而,该库可以自由地对输入进行分区,对分区进行归约,然后使用组合器功能将部分结果组合起来,以实现并行归约。 (根据具体的归约操作,这可能表现得更好或更差,具体取决于累加器和组合器功能的相对成本。)
收集器设计为 composed ;
Collectors中的许多方法都是采用收集器并生成新收集器的函数。例如,给定以下收集器计算员工流的工资总和:
如果我们想创建一个收集器来按部门列出工资总和,我们可以使用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
- 参见:
-
内部类总结
内部类 -
方法总结
修饰符和类型方法描述BiConsumer<A,T> 将值折叠到可变结果容器中的函数。返回Collector.Characteristics的Set指示此收集器的特征。combiner()接受两个部分结果并将它们合并的函数。finisher()执行从中间累积类型A到最终结果类型R的最终转换。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) 返回由给定的supplier、accumulator、combiner和finisher函数描述的新Collector。static <T,R> Collector<T, R, R> of(Supplier<R> supplier, BiConsumer<R, T> accumulator, BinaryOperator<R> combiner, Collector.Characteristics... characteristics) 返回由给定的supplier、accumulator和combiner函数描述的新Collector。supplier()创建并返回新的可变结果容器的函数。
-
方法详情
-
supplier
创建并返回新的可变结果容器的函数。- 返回:
- 返回一个新的可变结果容器的函数
-
accumulator
BiConsumer <A ,T > accumulator()将值折叠到可变结果容器中的函数。- 返回:
- 将值折叠到可变结果容器中的函数
-
combiner
BinaryOperator <A > combiner()接受两个部分结果并将它们合并的函数。组合器函数可以将状态从一个参数折叠到另一个参数并返回它,或者可以返回一个新的结果容器。- 返回:
- 将两个部分结果组合成组合结果的函数
-
finisher
执行从中间累积类型A到最终结果类型R的最终转换。如果设置了特征
IDENTITY_FINISH,则可以假定此函数是一个恒等变换,具有从A到R的未经检查的转换。- 返回:
- 将中间结果转换为最终结果的函数
-
characteristics
Set <Collector.Characteristics > characteristics()返回Collector.Characteristics的Set指示此收集器的特征。这个集合应该是不可变的。- 返回:
- 一组不可变的收集器特征
-
of
static <T,R> Collector <T,R, ofR> (Supplier <R> supplier, BiConsumer <R, T> accumulator, BinaryOperator <R> combiner, Collector.Characteristics ... characteristics) 返回由给定的supplier、accumulator和combiner函数描述的新Collector。生成的Collector具有Collector.Characteristics.IDENTITY_FINISH特性。- 类型参数:
T- 新收集器的输入元素类型R- 新收集器的中间累积结果类型和最终结果- 参数:
supplier- 新收集器的供应商功能accumulator- 新收集器的累加器函数combiner- 新收集器的组合器功能characteristics- 新收集器的收集器特性- 返回:
-
新的
Collector - 抛出:
NullPointerException- 如果任何参数为空
-
of
static <T,A, Collector <T,R> A, ofR> (Supplier <A> supplier, BiConsumer <A, T> accumulator, BinaryOperator <A> combiner, Function <A, R> finisher, Collector.Characteristics ... characteristics) 返回由给定的supplier、accumulator、combiner和finisher函数描述的新Collector。- 类型参数:
T- 新收集器的输入元素类型A- 新收集器的中间累积类型R- 新收集器的最终结果类型- 参数:
supplier- 新收集器的供应商功能accumulator- 新收集器的累加器函数combiner- 新收集器的组合器功能finisher- 新收集器的整理函数characteristics- 新收集器的收集器特性- 返回:
-
新的
Collector - 抛出:
NullPointerException- 如果任何参数为空
-