Коллекторы Stream API, часть 3: дизайн
Вчера мы разбирали groupingBy и partitioningBy. У многих возникла мысль, что лучше держаться от группировок подальше. Коллекторы выглядят неважно относительно других методов Stream API:
▪️Многословные: collect(Collectors.toSet())
▪️Вложенные коллекторы
▪️Дублированные методы map, flatMap, max, min - 18 штук
Итог: плохая читаемость и желание написать всё через цикл for.
Почему так получилось? Разберёмся в этом посте.
Выделим три вопроса:
1️⃣ Почему вместо toSet() такой сложный collect(Collectors.toSet())?
2️⃣ Почему группировка - терминальная операция?
3️⃣ Зачем в классе 18 неполноценных методов и вложенные коллекторы?
Разберём по порядку.
1️⃣ Метод collect и класс Collectors.
Цель Stream API - удобная работа с данными. За интерфейсом Stream может быть любой источник данных: список, строка, коллекция или файл. Сторонние библиотеки могут реализовать свой источник данных и работать с ним стандартными средствами Stream API.
В обратную сторону это тоже работает. Пользователь может преобразовать стрим в свою структуру данных, для этого в интерфейсе Stream метод collect(Collector).
А ещё источник данных и конечная структура данных - разные сущности, поэтому в интерфейсе Stream нет методов toSet(), toList(). Single Responsibility.
2️⃣ Почему группировка - терминальная операция?
С точки зрения пользователя группировка - просто преобразование. После группировки элементы можно фильтровать, менять и так далее.
Дизайн Stream API для этого не подходит. Источник данных делится на части, элементы обрабатываются независимо, иногда в разных потоках.
Терминальная операция - единственное место, где потоки объединяются и вычисляется общий результат. Посчитать количество, найти элемент, объединить в коллекцию - это конечные точки в обработке.
Группировка работает со всеми элементами, и в терминах Stream API это терминальная операция, дальше работать со стримом нельзя.
3️⃣ Вложенные коллекторы и 18 методов для groupingBy
Кстати, разработчики JDK понимают, что группировка - это преобразование данных, а вовсе не финальная точка.
Что может понадобиться программисту?
🔸Указать итоговый тип данных.
🔸Преобразовать итоговые данные. Это сложно сделать напрямую, потому что универсального интерфейса для filter, map и average нет.
Для решения этих задач groupingBy получил аргумент-коллектор, а Collectors пополнился 18 методами-обёртками над map, flatMap, filter и average .
На мой взгляд получилось сложновато, но это спорный вопрос. А какие вам нравятся библиотеки?
💅 - Удобные методы для целевых кейсов, но с ограничениями
💪 - Максимум возможностей и кастомизации
#core
Post #202
5.73K
- 👍 2
- ❤ 1