如何使用Java Stream API有效解析文本文件
我了解如何使用Java8流从文件中获取特定数据。例如,如果我们需要从这样的文件中获取加载的包s
2015-01-06 11:33:03 b.s.d.task [INFO] Emitting: eVentToRequestsBolt __ack_ack
2015-01-06 11:33:03 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package com.foo.bar
2015-01-06 11:33:04 b.s.d.executor [INFO] Processing received message source: eventToManageBolt:2, stream: __ack_ack, id: {}, [-6722594615019711369 -1335723027906100557]
2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package co.il.boo
2015-01-06 11:33:04 c.s.p.d.PackagesProvider [INFO] ===---> Loaded package dot.org.biz
我们能做到
List<String> packageList = Files.lines(Paths.get(args[1])).filter(line -> line.contains("===---> Loaded package"))
.map(line -> line.split(" "))
.map(arr -> arr[arr.length - 1]).collect(Collectors.toList());
我从Parsing File Example中获取(并稍微修改)了代码
但是,如果我们还需要从同一个日志文件中获取发出:事件的所有日期(和时间),该怎么办?我们如何在使用同一个流的情况下做到这一点
我只能想象在解析之前使用collect(groupingBy(...))
将带有加载包的行和带有发射:的行分组,然后分别解析每个组(一个映射条目)。但这将创建一个包含日志文件中所有原始数据的映射,这非常消耗内存
有没有类似的方法可以有效地从Java8流中提取多种类型的数据
# 1 楼答案
您可以使用我在this answer中编写的
pairing
收集器,它可以在我的StreamEx库中找到。对于您的具体问题,您还需要一个filtering
收集器,它可以在JDK-9早期访问版本中使用,也可以在我的StreamEx库中使用。如果您不喜欢使用第三方库,您可以从this答案复制它此外,还需要将所有内容存储到某些数据结构中。为此,我声明了
Data
类:把所有东西放在一起,你可以定义一个
parsingCollector
:然后像这样使用它:
# 2 楼答案
您可以在不定义新收集器的情况下解决此问题,也不必以更强制的方式使用第三方库。首先,您需要定义一个表示解析结果的类。它应该有两种方法来接受输入行并与现有的部分结果相结合:
现在,您可以以非常简单的方式收集: