- 类型参数:
-
T
- 缩减操作的输入元素的类型 -
A
- 缩减操作的可变累积类型(通常作为实现细节隐藏) -
R
- 缩减操作的结果类型
可变缩减操作的示例包括:将元素累积到一个Collection
中;使用StringBuilder
连接字符串;计算元素的汇总信息,如总和、最小值、最大值或平均值;计算“数据透视表”摘要,如“卖家的最大价值交易”等。类Collectors
提供了许多常见可变缩减的实现。
Collector
由四个函数指定,这些函数共同工作将条目累积到一个可变的结果容器中,并可选择对结果进行最终转换。它们是:
- 创建一个新的结果容器(
supplier()
) - 将新数据元素合并到结果容器中(
accumulator()
) - 将两个结果容器合并为一个(
combiner()
) - 对容器执行可选的最终转换(
finisher()
)
Collectors还具有一组特征,如Collector.Characteristics.CONCURRENT
,可提供提示,可供缩减实现使用以提供更好的性能。
使用收集器进行缩减的顺序实现将使用供应商函数创建一个单一结果容器,并为每个输入元素调用一次累加器函数。并行实现将对输入进行分区,为每个分区创建一个结果容器,将每个分区的内容累积到该分区的子结果中,然后使用组合器函数将子结果合并为一个组合结果。
为确保顺序和并行执行产生等效结果,收集器函数必须满足一个标识和一个结合性约束。
标识约束表示对于任何部分累积的结果,将其与空结果容器组合必须产生等效结果。也就是说,对于部分累积的结果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); // 不拆分的结果
A a2 = supplier.get();
accumulator.accept(a2, t1);
A a3 = supplier.get();
accumulator.accept(a3, t2);
R r2 = finisher.apply(combiner.apply(a2, a3)); // 拆分的结果
对于没有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);
但是,库可以自由地对输入进行分区,对分区执行缩减操作,然后使用组合器函数将部分结果组合以实现并行缩减。(根据特定缩减操作的相对累加器和组合器函数成本,这可能表现更好或更差。)
Collectors被设计为可组合;
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
- 参见:
-
Nested Class Summary
Modifier and TypeInterfaceDescriptionstatic enum
表示Collector
属性的特征,可用于优化缩减实现。 -
Method Summary
Modifier and TypeMethodDescriptionBiConsumer
<A, T> 将值折叠到可变结果容器中的函数。返回一个Set
,其中包含表示此Collector特征的Collector.Characteristics
。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()
创建并返回一个新的可变结果容器的函数。
-
Method Details
-
supplier
创建并返回一个新的可变结果容器的函数。- 返回:
- 一个函数,返回一个新的、可变的结果容器
-
accumulator
BiConsumer<A,T> accumulator()将值折叠到可变结果容器中的函数。- 返回:
- 一个函数,将值折叠到可变结果容器中
-
combiner
BinaryOperator<A> combiner()接受两个部分结果并合并它们的函数。组合器函数可以将一个参数的状态折叠到另一个参数中并返回,或者可以返回一个新的结果容器。- 返回:
- 一个函数,将两个部分结果组合成一个组合结果
-
finisher
执行从中间累积类型A
到最终结果类型R
的最终转换。如果设置了
IDENTITY_FINISH
特征,可以假定此函数是一个从A
到R
的标识转换,带有未经检查的强制转换。- 返回:
- 一个函数,将中间结果转换为最终结果
-
characteristics
Set<Collector.Characteristics> characteristics()返回一个Set
,其中包含指示此Collector特性的Collector.Characteristics
。这个集合应该是不可变的。- 返回:
- 一个不可变的collector特性集合
-
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
- 新collector的输入元素类型 -
R
- 新collector的中间累积结果和最终结果类型 - 参数:
-
supplier
- 新collector的供应函数 -
accumulator
- 新collector的累加函数 -
combiner
- 新collector的组合函数 -
characteristics
- 新collector的collector特性 - 返回:
-
新的
Collector
- 抛出:
-
NullPointerException
- 如果任何参数为null
-
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
- 新collector的输入元素类型 -
A
- 新collector的中间累积类型 -
R
- 新collector的最终结果类型 - 参数:
-
supplier
- 新collector的供应函数 -
accumulator
- 新collector的累加函数 -
combiner
- 新collector的组合函数 -
finisher
- 新collector的完成函数 -
characteristics
- 新collector的collector特性 - 返回:
-
新的
Collector
- 抛出:
-
NullPointerException
- 如果任何参数为null
-