T
- the type of input elements to the reduction operationA
- the mutable accumulation type of the reduction operation (often
hidden as an implementation detail)R
- the result type of the reduction operationpublic interface Collector<T,A,R>
Examples of mutable reduction operations include:
accumulating elements into a Collection
; concatenating
strings using a 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 Collector
implementations in Collectors
with the Stream
API to perform
mutable reduction tasks:
// Accumulate names into a List
List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());
// Accumulate names into a TreeSet
Set<String> 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<Department, List<Employee>> byDept
= employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));
// Find highest-paid employee by department
Map<Department, Optional<Employee>> highestPaidByDept
= employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment,
Collectors.maxBy(Comparators.comparing(Employee::getSalary))));
// Partition students into passing and failing
Map<Boolean, List<Student>> passingFailing =
students.stream()
.collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
A 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
Collector.Characteristics.CONCURRENT
. These characteristics provide
hints that can be used by a reduction implementation to provide better
performance.
Libraries that implement reduction based on Collector
, such as
Stream.collect(Collector)
, must adhere to the following constraints:
Collector
needing to implement any additional synchronization.
The reduction implementation must manage that the input is properly
partitioned, that partitions are processed in isolation, and combining
happens only after accumulation is complete.Collector.Characteristics.UNORDERED
characteristics or if the
originating data is unordered.Collector
should produce a
result equivalent to:
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 Collector
is accumulating elements into a TreeSet
. In this case, the resultSupplier()
function is () -> new Treeset<T>()
, the
accumulator
function is
(set, element) -> set.add(element)
, and the combiner
function is (left, right) -> { left.addAll(right); return left; }
.
(This behavior is implemented by
Collectors.toCollection(TreeSet::new)
).
TODO Associativity and commutativity
Stream.collect(Collector)
,
Collectors
Modifier and Type | Interface and Description |
---|---|
static class |
Collector.Characteristics
Characteristics indicating properties of a
Collector , which can
be used to optimize reduction implementations. |
Modifier and Type | Method and Description |
---|---|
BiConsumer<A,T> |
accumulator()
A function that folds a new value into a mutable result container.
|
Set<Collector.Characteristics> |
characteristics()
Returns a
Set of Collector.Characteristics indicating
the characteristics of this Collector. |
BinaryOperator<A> |
combiner()
A function that accepts two partial results and merges them.
|
Function<A,R> |
finisher()
Perform the final transformation from the intermediate accumulation type
A to the final result representation 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)
Returns a new
Collector described by the given supplier ,
accumulator , combiner , and finisher functions. |
static <T,R> Collector<T,R,R> |
of(Supplier<R> supplier,
BiConsumer<R,T> accumulator,
BinaryOperator<R> combiner,
Collector.Characteristics... characteristics)
Returns a new
Collector described by the given supplier ,
accumulator , and combiner functions. |
Supplier<A> |
supplier()
A function that creates and returns a new mutable result container.
|
Supplier<A> supplier()
BiConsumer<A,T> accumulator()
BinaryOperator<A> combiner()
Function<A,R> finisher()
A
to the final result representation R
.
If the characteristic IDENTITY_TRANSFORM
is
set, this function may be presumed to be an identity transform with an
unchecked cast from A
to R
.
Set<Collector.Characteristics> characteristics()
Set
of Collector.Characteristics
indicating
the characteristics of this Collector. This set should be immutable.static <T,R> Collector<T,R,R> of(Supplier<R> supplier, BiConsumer<R,T> accumulator, BinaryOperator<R> combiner, Collector.Characteristics... characteristics)
Collector
described by the given supplier
,
accumulator
, and combiner
functions. The resulting
Collector
has the Collector.Characteristics.IDENTITY_FINISH
characteristic.T
- The type of input elements for the new collectorR
- The type of intermediate accumulation result, and final result,
for the new collectorsupplier
- The supplier function for the new collectoraccumulator
- The accumulator function for the new collectorcombiner
- The combiner function for the new collectorcharacteristics
- The collector characteristics for the new
collectorCollector
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)
Collector
described by the given supplier
,
accumulator
, combiner
, and finisher
functions.T
- The type of input elements for the new collectorA
- The intermediate accumulation type of the new collectorR
- The final result type of the new collectorsupplier
- The supplier function for the new collectoraccumulator
- The accumulator function for the new collectorcombiner
- The combiner function for the new collectorfinisher
- The finisher function for the new collectorcharacteristics
- The collector characteristics for the new
collectorCollector
Submit a bug or feature
For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples.
Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.
DRAFT internal-0