/* * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.util.stream; import java.util.Collections; import java.util.EnumSet; 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 reduction operation that * folds input elements into a mutable result container, optionally transforming * the accumulated result into a final representation after all input elements * have been processed. * *
Examples of mutable reduction operations include: * accumulating elements into a {@code Collection}; concatenating * strings using a {@code StringBuilder}; computing summary information about * elements such as sum, min, max, or average; computing "pivot table" summaries * such as "maximum valued transaction by seller", etc. Reduction operations * can be performed either sequentially or in parallel. * *
The following are examples of using the predefined {@code Collector} * implementations in {@link Collectors} with the {@code Stream} API to perform * mutable reduction tasks: *
{@code * // Accumulate names into a List * List* *list = people.stream().map(Person::getName).collect(Collectors.toList()); * * // Accumulate names into a TreeSet * Set list = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new)); * * // Convert elements to strings and concatenate them, separated by commas * String joined = things.stream() * .map(Object::toString) * .collect(Collectors.joining(", ")); * * // Find highest-paid employee * Employee highestPaid = employees.stream() * .collect(Collectors.maxBy(Comparators.comparing(Employee::getSalary))) * .get(); * * // Group employees by department * Map > byDept * = employees.stream() * .collect(Collectors.groupingBy(Employee::getDepartment)); * * // Find highest-paid employee by department * Map > highestPaidByDept * = employees.stream() * .collect(Collectors.groupingBy(Employee::getDepartment, * Collectors.maxBy(Comparators.comparing(Employee::getSalary)))); * * // Partition students into passing and failing * Map > passingFailing = * students.stream() * .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD)); * * }
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: creation of a new result container, * incorporating a new data element into a result container, combining two * result containers into one, and performing a final transform on the container. * The combiner function is used during parallel operations, where * subsets of the input are accumulated into separate result * containers, and then the subresults merged into a combined result. The * combiner function may merge one set of subresults into the other and return * that, or it may return a new object to describe the combined results. * *
Collectors also have a set of characteristics, such as * {@link Characteristics#CONCURRENT}. These characteristics provide * hints that can be used by a reduction implementation to provide better * performance. * *
Libraries that implement reduction based on {@code Collector}, such as * {@link Stream#collect(Collector)}, must adhere to the following constraints: *
{@code * R container = collector.supplier().get(); * for (T t : data) * collector.accumulator().accept(container, t); * return collector.finisher().apply(container); * }* *
However, the library is free to partition the input, perform the reduction * on the partitions, and then use the combiner function to combine the partial * results to achieve a parallel reduction. Depending on the specific reduction * operation, this may perform better or worse, depending on the relative cost * of the accumulator and combiner functions. * *
An example of an operation that can be easily modeled by {@code Collector}
* is accumulating elements into a {@code TreeSet}. In this case, the {@code
* resultSupplier()} function is {@code () -> new Treeset 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 finisher();
/**
* Returns a {@code Set} of {@code Collector.Characteristics} indicating
* the characteristics of this Collector. This set should be immutable.
*
* @return an immutable set of collector characteristics
*/
Set 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 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
}
}