java - 依赖前一个和下一个元素的流处理

标签 java lambda java-8 java-stream

我必须处理包含预定义记录布局的固定宽度文件,存在多种类型的记录并且记录的第一个字符决定其类型。因为它是固定宽度的,所以不可能总是在一行中放满整个记录类型,所以第二个字符是记录的序号。例如:

0This is the header record------------------------------------
1This is another record always existing out of one lin--------
21This is a record that can be composed out of multiple parts.
22This is the second part of record type 2--------------------
21This is a new record of type 2, first part.-----------------
22This is the second part of record type 2--------------------
23This is the third part of record type 2---------------------
...

使用 Stream API,我想解析这个文件:

Stream<String> lines = Files.lines(Paths.get(args[1]));

lines.map(line -> RecordFactory.createRecord(line)).collect(Collectors.toList());

但是由于这个流是逐行传递的,当它解析记录类型 2 的第一行(记录类型 2 序列 1)时,记录 2 的映射是不完整的。下一行(记录类型 2 序列 2)应添加到先前映射的结果中。

我怎样才能用 lambda 解决这个问题而不必破坏线程安全?

最佳答案

目前使用 Stream API 不容易实现对匹配谓词的连续元素的操作。

一个选择是使用 StreamEx提供 groupRuns 的图书馆操作:

Returns a stream consisting of lists of elements of this stream where adjacent elements are grouped according to supplied predicate.

以下代码将连续行的记录部分号严格大于前一行的行组合在一起。记录号是用一个正则表达式提取的,该正则表达式查找第一个被忽略的数字之后的所有数字。

private static final Pattern PATTERN = Pattern.compile("\\d(\\d+)");

public static void main(String[] args) throws IOException {
    try (StreamEx<String> stream = StreamEx.ofLines(Paths.get("..."))) {
        List<Record> records =
            stream.groupRuns((s1, s2) -> getRecordPart(s2) > getRecordPart(s1))
                  .map(RecordFactory::createRecord)
                  .toList();
    }
}

private static final int getRecordPart(String str) {
    Matcher matcher = PATTERN.matcher(str);
    if (matcher.find()) {
        return Integer.parseInt(matcher.group(1));
    }
    return 1; // if the pattern didn't find anything, it means the record is on a single line
}

这假设您的 RecordFactory会创建一个 Record来自List<String>而不是来自 String .请注意,此解决方案可以并行运行,但将文件内容存储到 List 中可能会更好。如果您想要更好的并行性能(以内存为代价),则对该列表进行后处理。

关于java - 依赖前一个和下一个元素的流处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35147904/

相关文章:

java - 映射连接的算法

java - 如何将对象转换为给定的泛型类型,以便我可以将此对象传递给方法

c# - 使用嵌套的 LambdaExpressions 编译 LambdaExpression 时,它们也会编译吗?

c++ - 如何在 std 函数 lambda c++ 11 中正确捕获参数包

java - 我的正则表达式模式中的误解

java - ORA-01858:在Oracle ADF中发现了非数字字符

Java字符串修剪没有效果

java - 将Java日期从一种格式转换为另一种格式,而无需将其转换为字符串

java - 使用接口(interface)的默认方法实现方法 - 矛盾吗?

java - 如何将字符串拆分为映射,使用流按重复键对值进行分组?