Collector.java official document translation

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">Variable reduction (reduction/convergence) Operation</a>
* Accumulates elements into a mutable result container,
* optionally converts the accumulated result to a final representation after all input elements have been processed.
* Reduction operations can be performed serially or in parallel.
*
* <p> Examples of variable reduction operations include:
* accumulating elements into a {@code Collection},
* concatenating strings using {@code StringBuilder},
* computing elements such as sum, min, max, or average aggregated information,
* Calculate totals for "PivotTables" such as "Seller Max Transactions", etc.
* This class {@link Collectors} provides implementations of many common reduction operations.
*
* <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> Create a new result container ({@link #supplier()})</li>
* <li>merge a new data element into the result container ({@link #accumulator()})</li>
* <li>Merge the two result containers into one ({@link #combiner()})</li>
* <li>Perform an optional final transformation on the container ({@link #finisher()})</li> li>
* </ul>
*
* <p>Collectors have a series of characteristics, such as
* {@link Characteristics#CONCURRENT},


* <p>A serial implementation of a reduction operation using a collector would use the supplier functional interface
* to create a single result container and call the accumulator function once for each input element.
* The parallel implementation will partition the input, create a result container for each partition,
* accumulate the contents of each partition into the subresults for that partition (subresult), then use the combiner (merge)
* function to combine each subresult for the final result.
*
* <p>To ensure that serial execution and parallel execution produce equivalent results, the collector function must satisfy
*<em>identity</em> and <a href="package-summary.html#Associativity">associativity</em> a> Constraint
*
* The <p>identity constraint states that for any partially accumulated result, combining it with an empty result container,
* must produce a result equal to the final result.
* That is, for a partially accumulated result {@code a}, the result of any series of accumulator and
* combiner calls, {@code a} must be equal to {@code combiner.apply(a, supplier.get() )}.
*
* <p> associativity means that the division computation must produce equivalent results.
* That is, for any input elements {@code t1} and {@code t2}, the following
* In the calculation, the results {@code t1} and {@code t2} must be equal.
* <pre>{@code
* A a1 = supplier.get();
* accumulator.accept(a1, t1);
* accumulator.accept(a1, t2);
* R r1 = finisher.apply(a1); // Result is not split
*
* 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 split
* } </pre>
*
* <p>For collectors without the {@code UNORDERED} feature,
* two accumulated results{@ code a1} and {@code a2} are equivalent to er.apply(a1).equals(finisher.apply(a2))}.
* For unordered collectors, equivalence is relaxed, allowing equality in different order.
* (eg: an unordered collector accumulates elements into {@code List}, if they contain the same elements, ignoring the order
* will treat them as the same list).
*
* <p>The library implements the reduction operation based on {@code Collector}, for example: {@link Stream#collect(Collector)},
* must adhere to the following constraints:
* <ul>
* <li>Passed to the accumulator function The first parameter, the parameter passed to the combiner function,
* and the parameter passed to the finisher function must be
the result of the previous call to supplier, accumulator, combiner *.
*    
* <li>The implementation SHOULD NOT do anything with the * results of any supplier, accumulator, and combiner functions
, except pass them again to the accumulator, combiner, or finisher
* functions, or return them to the caller of the reduction operation .
*    
* <li>If the result is passed to a combiner or finisher function,
* and the same object is not returned from this function, it is not used again.
*    
* <li>Once a result is passed to the combiner or finisher functions,
* It will never be passed to the accumulator function again.
*    
*    
* <li>For non-concurrent collectors,
any results * returned from a supplier, accumulator, or combiner function must be serial thread bound.
* This allows the collection to execute concurrently without the need for {@code Collector} to implement
* any additional synchronization.
* Reduction implementations must manage input into its correct partitions, partitions are processed independently,
* and merged only after accumulation.
*    
*    
* <li>For concurrent collectors, implementation MAY be free (but not required) concurrent implementation reduction.
* Concurrent reduction is calling the accumulator function concurrently in multiple threads, using the same
* concurrently modifiable result container, rather than isolating this result during accumulation.
* Concurrent reduction should only be used if the collector has the {@link Characteristics#UNORDERED} characteristic or
* if the original data is unordered.
* </ul>
*
* <p>Except in {@link Collectors} Defined outside the implementation, static factory methods
* {@link #of(Supplier, BiConsumer, BinaryOperator, Characteristics...)} can also
* be used to build collectors. For example, you can create a collector to accumulate widgets into {@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
* Performing a reduction operation with {@code Collector} should yield the equivalent of:
* <pre>{@code
* R container = collector.supplier().get( );
* for (T t : data)
* collector.accumulator().accept(container, t);
* return collector.finisher().apply(container);
* }</pre>
*
* <p>However, the library is free to divide the input on partitions Perform a reduction operation,
* then use the combiner function to combine partial results for parallel reduction.
* (may perform better or worse depending on the specific reduction operation, depending on
* the associated accumulator and combiner function overhead)
*
* <p>Collectors are designed to be <em>composable</em> ;Many of the methods in {@link Collectors}
* take a new collector and generate a new one.
* For example, given the following collector, calculate the total salary of employees.
*
* <pre>{@code
* Collector<Employee, ?, Integer> summingSalaries
* = Collectors.summingInt(Employee::getSalary))
* }</pre>
*
* If we want to create a collector to count by department The sum of wages, we can use
* {@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> {
    /**
     * Function that creates and returns a new mutable result container.
     * @return a function which returns a new, mutable result container
     */
    Supplier<A> supplier();

    /**
     * A function which folds a value into a mutable result
     *
     * @return a function which folds a value into a mutable result container
     */
    BiConsumer<A, T> accumulator();

    /**
     * A function that takes two partial results and combines them.
     The * combiner function can stack state from one argument to another and return it,
     * or return a new result container.
     *
     * @return a function which combines two partial results into a combined
     * result
     */
    BinaryOperator<A> combiner();

    /**
     * Perform a conversion from intermediate result type {@code A} to final result type {@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();

    /**
     * Returns a {@code Set} of {@code Collector.Characteristics}, indicating
     * the characteristics of the collector. This collection should be immutable.
     *
     * @return an immutable set of collector characteristics
     */
    Set<Characteristics> characteristics();

    /** * Returns      the new collector described
     by the given {@code supplier}, {@code accumulator}, and {@code combiner} functions *.
This result {@code Collector} has {@code Collector.Characteristics.IDENTITY_FINISH}
     * characteristics
     *
     * @param supplier new collector's supplier function
     * @param accumulator new collector's accumulator function
     * @param combiner new collector's combiner function
     * @param characteristics The characteristics of the new collector
     *                      
     * @param <T> The type of the input element of the new collector
     * @param <R> The type of the intermediate calculation result and the final result of the new collector.
     * @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);
    }

    /**
     * Returns an array created by the given {@code supplier},
     * {@code accumulator}, {@code combiner} , and
     the collector described by the {@code finisher} function *.
     *
     * @param supplier the supplier function of the
     new collector * @param accumulator the accumulator function of the
     new collector * @param combiner the combiner function of the
     new collector * @param finisher the finisher function of the
     new collector * @param characteristics the characteristics of the new collector feature.
     *                   
     * @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);
    }

    /**
     * Characteristics indicate properties of {@code Collector} that
     * can be used to optimize reduction implementations.
     */
    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
    }
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326632380&siteId=291194637