Java! Есть возможность в Stream создать счетчик? Пояснения внутри

Неизвестно Мастер (2391), открыт 2 недели назад
Например, если мы пробегаем stream'ом по map и подсчитываем с нем количество каждого символа, то нужно уменьшать количество каждого символа на то, число которое мы нашли на каждой итерации.
1 ответ
Папа Высший разум (122400) 2 недели назад
Лучше всего - использовать метод collect стрима, который как раз и выполняет редукцию в мутабельный контейнер. Используй тот вариант, который не требует коллектора:
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#collect-java.util.function.Supplier-java.util.function.BiConsumer-java.util.function.BiConsumer-
Будет что-то типа:
 final Map freqs = stream...
... // тут вызываем методы map, filter, flatMap и прочее
...
.collect(HashMap::new,
(acc, v) -> {
acc.put(v, acc.getOrDefault(v, 0) + 1);
return acc;
},
(a1, a2) -> a1);
На выходе получаем freqs - соответствие значений и частот. Подкрути под свою задачу.

Другой вариант - завести мутабельный контейнер вне стрима, а от стрима позвать forEach, который будет вставлять/апдейтить элементы в тот внешний контейнер. Это быдлокодерский вариант, но довольно распространённый, т.к. большинство Java-программистов не в курсе о теории категорий (откуда родом map, reduce и т.п.) и не понимают этих концепций. На ревью я такие вещи обычно заворачивал, когда видел, и писал в комментарии пример, как это сделать через collect, т.к. код без побочных эффектов лучше поддаётся анализу, как глазами, так и компилятором и автоматизированными средствами.
Похожие вопросы