在不收集Java8流的情况下对其进行分组

时间:2016-08-18 08:33:41

标签: java java-8 grouping java-stream

Java 8中是否有任何方法可以在java.util.stream.Stream中对元素进行分组而不收集它们?我希望结果再次成为Stream。因为我必须处理大量数据甚至是无限流,所以我无法先收集数据并再次流式传输结果。

需要分组的所有元素在第一个流中是连续的。因此,我喜欢让流评估保持懒惰。

1 个答案:

答案 0 :(得分:25)

使用标准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))将创建字符串列表流,其中每个列表包含以相同字母开头的相邻字符串。

其他部分缩减操作包括intervalMaprunLengths()等等。

所有部分缩减操作都是惰性的,并行友好且非常有效。

请注意,您可以使用StreamEx从常规Java 8流中轻松构造StreamEx.of(stream)对象。还有一些方法可以从数组,Collection,Reader等构建它。StreamEx类实现Stream接口,并且与标准Stream API 100%兼容。