Ответ 1
Нет никакого способа сделать это, используя стандартный Stream API. В общем, вы не можете сделать это, так как всегда возможно, что в будущем будет отображаться новый элемент, который принадлежит к любой из уже созданных групп, поэтому вы не можете передать свою группу в анализ вниз, пока не обработаете все входные данные.
Однако, если вы заранее знаете, что элементы, которые должны быть сгруппированы, всегда смежны во входном потоке, вы можете решить свою проблему, используя сторонние библиотеки, улучшающие Stream API. Одна из таких библиотек - StreamEx, которая свободна и написана мной. Он содержит ряд операторов "частичной редукции", которые сворачивают соседние элементы в отдельные на основе некоторого предиката. Обычно вы должны указать BiPredicate
, который проверяет два соседних элемента и возвращает true, если они должны быть сгруппированы вместе. Ниже перечислены некоторые операции частичного восстановления:
-
collapse(BiPredicate)
: замените каждую группу на первый элемент группы. Например,collapse(Objects::equals)
полезен для удаления соседних дубликатов из потока. -
groupRuns(BiPredicate)
: замените каждую группу на список элементов группы (поэтомуStreamEx<T>
преобразуется вStreamEx<List<T>>
). Например,stringStream.groupRuns((a, b) -> a.charAt(0) == b.charAt(0))
создаст поток списков строк, в котором каждый список содержит смежные строки, начинающиеся с той же буквы.
Другие операции частичного сокращения включают intervalMap
, runLengths()
и т.д.
Все операции частичного сокращения являются ленивыми, параллельными и эффективными.
Обратите внимание, что вы можете легко построить объект StreamEx
из обычного потока Java 8, используя StreamEx.of(stream)
. Также есть методы для его создания из массива, Collection, Reader и т.д. Класс StreamEx
реализует интерфейс Stream
и 100% совместим со стандартным Stream API.