2016-08-18 5 views
19

Есть ли способ в Java 8 сгруппировать элементы в java.util.stream.Stream без их сбора? Я хочу, чтобы результат снова был Stream. Поскольку мне приходится работать с большим количеством данных или даже бесконечными потоками, я не могу сначала собрать данные и снова передать результат.Группировка потока Java8 без его сбора

Все элементы, которые необходимо сгруппировать, являются последовательными в первом потоке. Поэтому мне нравится держать ленту оценкой ленивой.

+2

Если ваши данные уже «предварительно сгруппированы» (путем последовательного), зачем вам это нужно в сгруппированной форме? Предоставление некоторого контекста может помочь дать лучший ответ на этот вопрос. –

+0

Вы имеете в виду использование 'groupBy' из' Collectors' без сбора? – ByeBye

+1

Звучит как работа для очереди, а не поток. Потребляйте последовательные элементы из очереди, пока не обнаружите начало, если следующая группа, добавьте группу в следующую очередь, содержащую группы. – Hulk

ответ

19

Нет никакого способа сделать это, используя стандартный 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% совместим со стандартным API потока.

+0

Я проведу вашу библиотеку. Кажется, это именно то, что мне нужно. Спасибо за предложение. –

+2

Хм, интересно. Было бы очень приятно видеть, что это применяется к фактическому коду OPs, @MatthiasWimmer –

Смежные вопросы