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-8 lambda 表达式中使用 if-else 语句

c# - 将表达式和 lambdas 参数传递给 F# 中的 C# 扩展方法

loops - 将循环内的复杂条件逻辑转换为流和 lambda

java - 如果谓词中给出了所有条件,则获取所有匹配的非空元素

java - 如何在 xslt 转换期间处理 org.apache.xml.utils.WrappedRuntimeException?

java - @CreationTimestamp 和@UpdateTimestamp 不适用于 LocalDateTime

Java 链表并发修改异常

java - 我应该如何在 Spring MVC 中创建 Groovy Controller

lambda - 资格跟踪 : On-line vs Off-line λ-return algorithm

java - 为什么java 8使用默认方法而不是扩展方法