Collector.java官方文档翻译

package java.util.stream;

import java.util.Collections;
import java.util.EnumSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;


/**
* A <a href="package-summary.html#Reduction">可变的reduction(归约/汇聚)操作</a>
* 将元素累加到可变的结果容器中,在所有的输入元素都被处理后,
* 可以选择性的将累加的结果转换为最终的表示。
* 归约操作可以串行或者并行的 执行。
*
* <p>可变reduction操作包括的例子有:
* 将元素 累加到一个 {@code Collection},
* 使用 {@code StringBuilder}连接字符串,
* 计算诸如sum, min, max, 或者 average等元素的汇总信息,
* 计算“数据透视表”的总数,比如“卖方最大值交易”等。
* 这个类 {@link Collectors} 提供了 很多常用归约操作的实现。
*
* <p>A {@code Collector} is specified by four functions that work together to
* accumulate entries into a mutable result container, and optionally perform
* a final transform on the result.  They are: <ul>
*     <li>创建一个新的结果容器 ({@link #supplier()})</li>
*     <li>将一个新的数据元素合并到结果容器中({@link #accumulator()})</li>
*     <li>将两个结果容器合并为一个  ({@link #combiner()})</li>
*     <li>在容器上执行可选的最终转换 ({@link #finisher()})</li>
* </ul>
*
* <p>Collectors 有一系列的特征, 比如
* {@link Characteristics#CONCURRENT},
* 提供了可以使用的归约操作的提示,以提供更好的性能
*
* <p>使用collector进行的归约操作的串行实现将使用supplier函数式接口
* 创建单个结果容器,并为每个输入元素调用一次累加器函数。
* 并行实现将对输入进行分区,为每个分区创建一个结果容器,
* 将每个分区的内容累加到该分区的子结果中(subresult),然后使用combiner(合并)
* 函数将每个子结果归并为最终结果。
*
* <p>为了确保串行执行和并行执行产生等价的结果,collector函数必须满足
*<em>identity</em> 以及<a href="package-summary.html#Associativity">associativity</a> 约束
*
* <p>identity(同一性 )约束表示,对于任何部分累积 的结果,将其与空的结果容器相结合,
* 就必须产生和最终结果相等的结果。
* 也就是说,对于部分累积的结果 {@code a},是任何一系列的accumulator和
* combiner调用的结果,{@code a}必须等于{@code combiner.apply(a, supplier.get())}.
*
* <p> associativity(结合性)是说,分割计算必须产生等价的结果。
* 也就是说,对于任何输入元素{@code t1}和 {@code t2},再下面的
* 计算中,结果{@code t1}和 {@code t2}必须相等。
* <pre>{@code
*     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));  // 结果分割
* } </pre>
*
* <p>对于那么没有{@code UNORDERED} 特性的收集器来说,
* 两个累加的结果 {@code a1} 和 {@code a2}相当于er.apply(a1).equals(finisher.apply(a2))}。
* 对于无序的收集器,等效性是宽松的,允许顺序不同的相等。
* (例如:一个无序的收集器将元素累积到{@code List},如果它们包含相同的元素,忽略顺序的话
* 将会把它们看作是相同的列表)。
*
* <p>库基于{@code Collector}实现归约操作,比如: {@link Stream#collect(Collector)},
* 必须坚持以下的约束:
* <ul>
*     <li>传递给accumulator函数的第一个参数,传递给combiner函数的参数,
*     以及传递给finisher函数的参数必须是supplier,accumulator,combiner
*     之前调用的结果。
*    
*     <li>该实现不应该对任何supplier, accumulator, 和 combiner函数的
*     结果进行任何操作,除了再次将它们传递给accumulator, combiner, 或 finisher
*     函数,或者将它们返回给reuction操作的调用方。
*    
*     <li>如果结果传递给combiner或者finisher函数,
*     并且同一个对象不会从这个函数中返回,则不再次使用它。
*    
*     <li>一旦一个结果被传递给combiner函数或者finisher 函数,
*     它就决不会再传递给accumulator函数。
*    
*    
*     <li>对于非并发的收集器,从supplier,accumulator,或者combiner函数中
*     返回的任何结果都必须是串行线程限制的。
*     这使得集合可以并发执行,而不需要 {@code Collector} 来实现
*     任何额外的同步 。
*    reduction实现必须 管理好输入将其正确的分区,分区被独立的处理,
*    并且只有在累加之后才进行合并。
*    
*    
*     <li>对于并发的收集器,实现可以是自由的(但不要求)并发实现reduction。
*     并发的reduction是在多个线程中同时调用accumulator函数,使用相同的
*     可并发修改的结果容器,而不是在累积过程中使这个结果隔离。
*     只有当收集器有  {@link Characteristics#UNORDERED} 特性时 或者
*     原始数据是无序时,才应该使用并发的reduction.
* </ul>
*
* <p>除了在 {@link Collectors}中预定义的实现外,静态工厂方法
*  {@link #of(Supplier, BiConsumer, BinaryOperator, Characteristics...)}也能够
*  用来构建收集器。例如,你可以创建收集器累加widgets到{@code TreeSet}中:
*
* <pre>{@code
*     Collector<Widget, ?, TreeSet<Widget>> intoSet =
*         Collector.of(TreeSet::new, TreeSet::add,
*                      (left, right) -> { left.addAll(right); return left; });
* }</pre>
*
* (This behavior is also implemented by the predefined collector
* {@link Collectors#toCollection(Supplier)}).
*
* @apiNote
* 使用 {@code Collector}执行一个reduction操作应该产生和下面等价的结果 :
* <pre>{@code
*     R container = collector.supplier().get();
*     for (T t : data)
*         collector.accumulator().accept(container, t);
*     return collector.finisher().apply(container);
* }</pre>
*
* <p>然而,库可以自由的划分输入,在分区上执行reduction操作,
* 然后使用combiner函数合并部分结果实现并行reduction 。
* (取决于特定的reduction操作,可能执行的更好或者更差,依赖于
* 相关的accumulator和combiner函数的开销)
*
* <p>收集器被设计成 <em>可组合的 </em>;在 {@link Collectors}
* 的许多方法都是接收一个新的收集器然后生成一个新的收集器。
* 比如,给定如下收集器,计算员工的工资总和。
*
* <pre>{@code
*     Collector<Employee, ?, Integer> summingSalaries
*         = Collectors.summingInt(Employee::getSalary))
* }</pre>
*
* 如果我们想要创建一个收集器来按部门 计算工资的总和 ,我们可以使用
* {@link Collectors#groupingBy(Function, Collector)}来重用“薪水总和”的逻辑。
*
* <pre>{@code
*     Collector<Employee, ?, Map<Department, Integer>> summingSalariesByDept
*         = Collectors.groupingBy(Employee::getDepartment, summingSalaries);
* }</pre>
*
* @see Stream#collect(Collector)
* @see Collectors
*
* @param <T> the type of input elements to the reduction operation
* @param <A> the mutable accumulation type of the reduction operation (often
*            hidden as an implementation detail)
* @param <R> the result type of the reduction operation
* @since 1.8
*/
public interface Collector<T, A, R> {
    /**
     *创建并返回一个新的可变结果容器的函数。
     * @return a function which returns a new, mutable result container
     */
    Supplier<A> supplier();

    /**
     * 将值 汇聚成可变结果的函数
     *
     * @return a function which folds a value into a mutable result container
     */
    BiConsumer<A, T> accumulator();

    /**
     * 一个接收两个部分结果并将其合并的函数。
     * combiner函数可以将状态从一个参数叠加到另一个参数,并将其返回,
     * 或者返回一个新的结果容器。
     *
     * @return a function which combines two partial results into a combined
     * result
     */
    BinaryOperator<A> combiner();

    /**
     *执行从中间结果类型{@code A}到最终结果类型 {@code R}的转换。
     *
     * <p>If the characteristic {@code IDENTITY_TRANSFORM} is
     * set, this function may be presumed to be an identity transform with an
     * unchecked cast from {@code A} to {@code R}.
     *
     * @return a function which transforms the intermediate result to the final
     * result
     */
    Function<A, R> finisher();

    /**
     * 返回 {@code Collector.Characteristics} 的{@code Set},指出
     * 收集器的 特征。这个集合应该是不可变的 。
     *
     * @return an immutable set of collector characteristics
     */
    Set<Characteristics> characteristics();

    /**
     * 返回由给定的{@code supplier}, {@code accumulator}, 和 {@code combiner} 函数
     * 描述的新的收集器。此结果{@code Collector}具有{@code Collector.Characteristics.IDENTITY_FINISH}
     * 特征
     *
     * @param supplier 新收集器的supplier函数
     * @param accumulator  新 收集器的accumulator函数
     * @param combiner 新收集器的combiner函数
     * @param characteristics 新收集器的特征
     *                      
     * @param <T> 新收集器输入元素的 类型
     * @param <R> 新收集器中间计算结果和最终结果的类型。
     * @throws NullPointerException if any argument is null
     * @return the new {@code Collector}
     */
    public static<T, R> Collector<T, R, R> of(Supplier<R> supplier,
                                              BiConsumer<R, T> accumulator,
                                              BinaryOperator<R> combiner,
                                              Characteristics... characteristics) {
        Objects.requireNonNull(supplier);
        Objects.requireNonNull(accumulator);
        Objects.requireNonNull(combiner);
        Objects.requireNonNull(characteristics);
        Set<Characteristics> cs = (characteristics.length == 0)
                                  ? Collectors.CH_ID
                                  : Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH,
                                                                           characteristics));
        return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, cs);
    }

    /**
     * 返回一个由给定的 {@code supplier},
     * {@code accumulator}, {@code combiner}, 和 {@code finisher} 函数
     * 描述的收集器 。
     *
     * @param supplier 新收集器的supplier函数
     * @param accumulator 新收集器的accumulator函数
     * @param combiner新收集器的combiner函数
     * @param finisher 新收集器的finisher函数
     * @param characteristics 新收集器的characteristics特征 。
     *                   
     * @param <T> The type of input elements for the new collector
     * @param <A> The intermediate accumulation type of the new collector
     * @param <R> The final result type of the new collector
     * @throws NullPointerException if any argument is null
     * @return the new {@code Collector}
     */
    public static<T, A, R> Collector<T, A, R> of(Supplier<A> supplier,
                                                 BiConsumer<A, T> accumulator,
                                                 BinaryOperator<A> combiner,
                                                 Function<A, R> finisher,
                                                 Characteristics... characteristics) {
        Objects.requireNonNull(supplier);
        Objects.requireNonNull(accumulator);
        Objects.requireNonNull(combiner);
        Objects.requireNonNull(finisher);
        Objects.requireNonNull(characteristics);
        Set<Characteristics> cs = Collectors.CH_NOID;
        if (characteristics.length > 0) {
            cs = EnumSet.noneOf(Characteristics.class);
            Collections.addAll(cs, characteristics);
            cs = Collections.unmodifiableSet(cs);
        }
        return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, finisher, cs);
    }

    /**
     * 特征表明了{@code Collector}的属性,该属性
     * 可用于优化reduction实现。
     */
    enum Characteristics {
        /**
         * Indicates that this collector is <em>concurrent</em>, meaning that
         * the result container can support the accumulator function being
         * called concurrently with the same result container from multiple
         * threads.
         *
         * <p>If a {@code CONCURRENT} collector is not also {@code UNORDERED},
         * then it should only be evaluated concurrently if applied to an
         * unordered data source.
         */
        CONCURRENT,

        /**
         * Indicates that the collection operation does not commit to preserving
         * the encounter order of input elements.  (This might be true if the
         * result container has no intrinsic order, such as a {@link Set}.)
         */
        UNORDERED,

        /**
         * Indicates that the finisher function is the identity function and
         * can be elided.  If set, it must be the case that an unchecked cast
         * from A to R will succeed.
         */
        IDENTITY_FINISH
    }
}

猜你喜欢

转载自linkinzlz.iteye.com/blog/2397435