Интерфейс 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 должно дать результат, эквивалентный
R 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 class  Collector.Characteristics

Характеристики, указывающие свойства Collector, которые могут использоваться для оптимизации реализаций сокращения.

Методы

Модификатор и тип Метод Описание
BiConsumer<A,​T> accumulator()

Функция, которая складывает значение в изменяемый контейнер результата.

Set<Collector.Characteristics> characteristics()

Возвращает Set Collector.Characteristics, указывающий характеристики этого Collector.

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()

Функция, которая принимает два частичных результата и объединяет их. Функция combiner может складывать состояние из одного аргумента в другой и вернуть его или вернуть новый контейнер результата.

Возвращает:
функцию, которая объединяет два частичных результата в объединённый результат

finisher

Function<A,R> finisher()

Выполняет окончательное преобразование от промежуточного типа накопления A к конечному типу результата R.

Если характеристика IDENTITY_FINISH установлена, эта функция может считаться преобразованием тождества с неконтролируемым приведением типа от A к R.

Возвращает:
функцию, которая преобразует промежуточный результат в конечный результат

characteristics

Set<Collector.Characteristics> characteristics()

Возвращает Set Collector.Characteristics , указывающую характеристики этого Collector. Этот набор должен быть неизменяемым.

Возвращает:
неизменяемый набор характеристик коллектора

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, 2020, 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/11/docs/api/java.base/java/util/stream/Collector.html

Spec-Zone .ru
спецификации, руководства, описания, API