Интерфейс Collector<T, A, R>
- Параметры типа:
T— тип входных элементов для операции редукцииA— изменяемый тип накапливаемых данных для операции редукции (часто скрыт как деталь реализации)R— тип результата операции редукции
public interface Collector<T,A,R>
Примеры изменяемых операций редукции: накопление элементов в Collection; объединение строк с помощью StringBuilder; вычисление сводной информации об элементах, например суммы, минимума, максимума или среднего значения; вычисление сводных данных в виде «сводной таблицы», например «транзакция с наибольшей стоимостью по продавцу» и т. д. Класс Collectors предоставляет реализации многих распространённых изменяемых редукций.
Collector задаётся четырьмя функциями, которые совместно накапливают элементы в изменяемом контейнере результата и, при необходимости, выполняют итоговое преобразование результата. Это:
- создание нового контейнера результата (
supplier()) - добавление нового элемента данных в контейнер результата (
accumulator()) - объединение двух контейнеров результата в один (
combiner()) - выполнение необязательного итогового преобразования контейнера (
finisher())
У коллекторов также есть набор характеристик, например 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); // result without splitting
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 with splitting
Для коллекторов, не имеющих характеристики 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— это функции, принимающие коллектор и возвращающие новый коллектор. Например, рассмотрим следующий коллектор, вычисляющий сумму зарплат сотрудников в потоке:
Чтобы создать коллектор, подсчитывающий сумму зарплат по отделам, можно повторно использовать логику «суммы зарплат» с помощью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
- См. также:
Краткое описание вложенных классов
| Модификатор и тип | Интерфейс | Описание |
|---|---|---|
static enum |
Collector.Characteristics |
Характеристики, указывающие свойства Collector, которые можно использовать для оптимизации реализаций редукции. |
Краткое описание методов
| Модификатор и тип | Метод | Описание |
|---|---|---|
BiConsumer |
accumulator() |
Функция, добавляющая значение в изменяемый контейнер результата. |
Set |
characteristics() |
Возвращает Set из Collector.Characteristics, указывающий характеристики этого коллектора. |
BinaryOperator |
combiner() |
Функция, принимающая два промежуточных результата и объединяющая их. |
Function |
finisher() |
Выполняет окончательное преобразование из промежуточного типа накапливаемых данных A в итоговый тип результата R. |
static <T, |
of |
Возвращает новый Collector, описанный заданными функциями supplier, accumulator, combiner и finisher. |
static <T, |
of |
Возвращает новый Collector, описанный заданными функциями supplier, accumulator и combiner. |
Supplier |
supplier() |
Функция, создающая и возвращающая новый изменяемый контейнер результата. |
Подробное описание методов
supplier
Supplier<A> supplier()
- Возвращает:
- функцию, возвращающую новый изменяемый контейнер результата
accumulator
BiConsumer<A,T> accumulator()
- Возвращает:
- функцию, добавляющую значение в изменяемый контейнер результата
combiner
BinaryOperator<A> combiner()
- Возвращает:
- функцию, объединяющую два промежуточных результата в один итоговый результат
finisher
Function<A,R> finisher()
A в итоговый тип результата R. Если задана характеристика IDENTITY_FINISH, эту функцию можно считать тождественным преобразованием с непроверяемым приведением типа от A к R.
- Возвращает:
- функцию, преобразующую промежуточный результат в итоговый
characteristics
Set<Collector.Characteristics> characteristics()
Set из Collector.Characteristics, указывающий характеристики этого коллектора. Этот набор должен быть неизменяемым.- Возвращает:
- неизменяемый набор характеристик коллектора
of
static <T,R> Collector<T,R,R> of(Supplier<R> supplier, BiConsumer<R,T> accumulator, BinaryOperator<R> combiner, Collector.Characteristics... characteristics)
Collector, описанный заданными функциями supplier, accumulator и combiner. Полученный Collector имеет характеристику Collector.Characteristics.IDENTITY_FINISH.- Параметры типа:
T— тип входных элементов для нового коллектораR— тип промежуточного результата накопления и итогового результата для нового коллектора- Параметры:
-
supplier— функция-поставщик для нового коллектора -
accumulator— функция-аккумулятор для нового коллектора -
combiner— функция-комбайнер для нового коллектора -
characteristics— характеристики нового коллектора - Возвращает:
- новый
Collector - Вызывает исключение:
-
NullPointerException— если какой-либо аргумент равен null
of
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, описанный заданными функциями supplier, accumulator, combiner и finisher.- Параметры типа:
T— тип входных элементов для нового коллектораA— промежуточный тип накапливаемых данных нового коллектораR— итоговый тип результата нового коллектора- Параметры:
-
supplier— функция-поставщик для нового коллектора -
accumulator— функция-аккумулятор для нового коллектора -
combiner— функция-комбайнер для нового коллектора -
finisher— функция-финишер для нового коллектора -
characteristics— характеристики нового коллектора - Возвращает:
- новый
Collector - Вызывает исключение:
-
NullPointerException— если какой-либо аргумент равен null
© 1993, 2025, Oracle and/or its affiliates. All rights reserved.
Documentation extracted from Debian's OpenJDK Development Kit package.
Licensed under the GNU General Public License, version 2, with the Classpath Exception.
Various third party code in OpenJDK is licensed under different licenses (see Debian package).
Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/stream/Collector.html