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