Java 8 Stream API, часть шестая: собственный коллектор

Turbo CollectorВо второй статье о использовании Stream API я показывал, как использовать стандартные коллекторы. Настало время разработки собственного коллектора.

Допустим, мы ходим посчитать медианное значение длин строк в примере из второй статьи. Готового коллектора, который считает медиану, нет в стандартной библиотеке, поэтому разработаем свой.

Мы реализуем интерфейс Collector, который типизируется тремя разными типами: входной тип для коллектора ( Integer в нашем случае), тип контейнера для хранения промежуточных вычислений ( TreeSet в нашем случае) и выходной тип коллектора, который он возвращает (опять Integer).

Интерфейс Collector требует реализации пяти методов. Supplier возвращает лямбда-выражение, создающее контейнер для хранения промежуточных выражений:

Accumulator добавляет очередное значение в контейнер промежуточных значений. Если быть точным, то accumulator возвращает лямбда-выражение, которое обрабатывает очередное значение и сохраняет его.

Combiner возвращает лямбда-выражение, объединяющее два контейнера промежуточных значений в один. Дело в том, что Stream API может создать несколько таки контейнеров, для параллельной обработки и в конце слить их в один общий контейнер.

Finisher возвращает лямбда-выражение, которое производит финальное преобразование: обрабатывает содержимого контейнера промежуточных результатов и приводит его к заданному выходному типу.

Последний вызов служит для декларирования свойств коллектора.

Полученный коллектор может быть использован в вызове collect():

 

Вместо собственной реализации интерфейса Collector можно использовать статический метод Collector.of(), принимающий те же самые лямбда выражения и вовзращающий настроенный коллектор.

Код примера доступен на github.