Spec-Zone.ru › OpenJDK 25

Интерфейс 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
См. также:
  • Stream.collect(Collector)
  • Collectors

Краткое описание вложенных классов

Модификатор и тип Интерфейс Описание
static enum  Collector.Characteristics
Характеристики, указывающие свойства Collector, которые можно использовать для оптимизации реализаций редукции.

Краткое описание методов

Модификатор и тип Метод Описание
BiConsumer<A,T> accumulator()
Функция, добавляющая значение в изменяемый контейнер результата.
Set<Collector.Characteristics> characteristics()
Возвращает Set из Collector.Characteristics, указывающий характеристики этого коллектора.
BinaryOperator<A> combiner()
Функция, принимающая два промежуточных результата и объединяющая их.
Function<A,R> finisher()
Выполняет окончательное преобразование из промежуточного типа накапливаемых данных A в итоговый тип результата 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)
Возвращает новый Collector, описанный заданными функциями supplier, accumulator, combiner и finisher.
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.
Supplier<A> 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

Сообщить об ошибке или предложить улучшение
Дополнительные справочные материалы по API и документацию для разработчиков см. в документации Java SE, содержащей более подробные описания для разработчиков, в том числе обзоры концепций, определения терминов, способы обхода ограничений и примеры работающего кода. Другие версии.
Java является товарным знаком или зарегистрированным товарным знаком Oracle и/или её аффилированных лиц в США и других странах.
Авторское право © 1993, 2025, Oracle и/или её аффилированные лица, 500 Oracle Parkway, Redwood Shores, CA 94065 USA.
Все права защищены. Использование регулируется условиями лицензии и политикой распространения документации.

© 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API