繁体   English   中英

Java8:如何从流中聚合对象?

[英]Java8 : how to aggregate objects from a stream?

编辑

如何从有序流中聚合项目,最好是在中间操作中?

语境

按照我的另一个问题: Java8 流线和聚合与终端线上的行动

我有一个非常大的表格文件:

MASTER_REF1
    SUBREF1
    SUBREF2
    SUBREF3
MASTER_REF2
MASTER_REF3
    SUBREF1
    ...

其中 SUBREF(如果有)适用于 MASTER_REF 并且两者都是复杂对象(你可以想象它有点JSON)。

乍一看,我尝试使用在聚合时返回null的操作对行进行分组,并在可以找到一组行时返回一个值(如果line.charAt(0)!=' '则“一组”行结束)。

这段代码很难阅读并且需要一个.filter(Objects::nonNull)

我认为人们可以利用这一个实现.collect(groupingBy(...)).reduce(...)但这些都是终端的操作是:

  • 在我的情况下不需要:线是有序的,应该按它们的位置分组,之后要转换线组(map+filter+...+foreach);
  • 也不是一个好主意:我说的是一个巨大的数据文件,它比 RAM+SWAP 的总量大得多……终端操作会使可用资源饱和(如上所述,根据设计,我需要将组保留在内存中,因为以后要改造)

正如我在上一个问题的回答中已经指出的那样,可以使用一些提供部分归约操作的第三方库。 其中一个库是我自己开发的StreamEx

在 StreamEx 库中,部分归约操作是中间流操作,它在满足某些条件时组合多个输入元素。 通常条件是通过应用于相邻流元素对的BiPredicate指定的,当元素应该组合在一起时返回true 组合元素的最简单方法是通过StreamEx.groupRuns()方法创建一个List ,如下所示:

Stream<List<String>> records = StreamEx.of(Files.lines(path))
    .groupRuns((line1, line2) -> !line2.startsWith("MASTER"));

在这里,当两条相邻行中的第二行以"MASTER"开头时,我们开始一条新记录(如您的示例所示)。 否则我们继续之前的记录。

请注意,这样的流仍然是惰性的。 在顺序处理中,一次最多创建一个中间List<String> 还支持并行处理,尽管将Files.lines流转换为并行模式很少能提高性能(至少在 Java-9 之前)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM