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.lang.NullPointerException

java - 在 fragment 中获取结果的问题

java - 如何避免在此 Java lambda 表达式代码中出现 NullPointerException 警告?

model-view-controller - MVC View : Type arguments Html helper DisplayFor cannot be inferred from the usage

java - 将我们的应用程序从Oracle JRE迁移到openJDK JRE是否有任何影响?

java - 在多次 POST/DELETE/PUT 后仅运行一次函数(例如清理)

java - InputStreamReader编码器

c++ - 无法将 lambda 转换为 std::function

java - 将复杂的 while 循环重构为 Java 8 流