Java 8中是否有任何方法可以在java.util.stream.Stream
中对元素进行分组而不收集它们?我希望结果再次成为Stream
。因为我必须处理大量数据甚至是无限流,所以我无法先收集数据并再次流式传输结果。
需要分组的所有元素在第一个流中是连续的。因此,我喜欢让流评估保持懒惰。
答案 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))
将创建字符串列表流,其中每个列表包含以相同字母开头的相邻字符串。其他部分缩减操作包括intervalMap
,runLengths()
等等。
所有部分缩减操作都是惰性的,并行友好且非常有效。
请注意,您可以使用StreamEx
从常规Java 8流中轻松构造StreamEx.of(stream)
对象。还有一些方法可以从数组,Collection,Reader等构建它。StreamEx
类实现Stream
接口,并且与标准Stream API 100%兼容。