当前位置: 首页 > 面试题库 >

累积Java流,然后再对其进行处理

管梓
2023-03-14
问题内容

我有一个看起来像下面的文档:

data.txt

100, "some text"
101, "more text"
102, "even more text"

我使用正则表达式对其进行了处理,并返回了如下的新处理文档:

Stream<String> lines = Files.lines(Paths.get(data.txt);
Pattern regex = Pattern.compile("([\\d{1,3}]),(.*)");

List<MyClass> result = 
  lines.map(regex::matcher)
       .filter(Matcher::find)
       .map(m -> new MyClass(m.group(1), m.group(2)) //MyClass(int id, String text)
       .collect(Collectors.toList());

这将返回已处理的MyClass的列表。可以并行运行,一切正常。

问题是我现在有这个:

data2.txt

101, "some text
the text continues in the next line
and maybe in the next"
102, "for a random
number
of lines"
103, "until the new pattern of new id comma appears"

因此,我需要以某种方式加入正在从流中读取的行,直到出现新的匹配项为止。(有点像缓冲区吗?)

我尝试收集字符串,然后收集MyClass(),但没有成功,因为我实际上无法拆分流。

减少连接线的想法,但是我只能连接线,而不能减少并生成新的线流。

有什么想法如何用Java 8 Streams解决这个问题吗?


问题答案:

这是的工作java.util.Scanner。随着即将发布的Java 9,您将编写:

List<MyClass> result;
try(Scanner s=new Scanner(Paths.get("data.txt"))) {
    result = s.findAll("(\\d{1,3}),\\s*\"([^\"]*)\"")
                //MyClass(int id, String text)
    .map(m -> new MyClass(Integer.parseInt(m.group(1)), m.group(2))) 
    .collect(Collectors.toList());
}
result.forEach(System.out::println);

但是由于Stream生产findAll在Java 8中不存在,因此我们需要一个辅助方法:

private static Stream<MatchResult> matches(Scanner s, String pattern) {
    Pattern compiled=Pattern.compile(pattern);
    return StreamSupport.stream(
        new Spliterators.AbstractSpliterator<MatchResult>(1000,
                         Spliterator.ORDERED|Spliterator.NONNULL) {
        @Override
        public boolean tryAdvance(Consumer<? super MatchResult> action) {
            if(s.findWithinHorizon(compiled, 0)==null) return false;
            action.accept(s.match());
            return true;
        }
    }, false);
}

findAll用这种辅助方法代替,我们得到

List<MyClass> result;
try(Scanner s=new Scanner(Paths.get("data.txt"))) {

    result = matches(s, "(\\d{1,3}),\\s*\"([^\"]*)\"")
               // MyClass(int id, String text)
    .map(m -> new MyClass(Integer.parseInt(m.group(1)), m.group(2)))
    .collect(Collectors.toList());
}


 类似资料:
  • 我正在编写一个使用NIO套接字的Java应用程序。它由3台服务器和一组客户端组成。客户端可以与服务器通信,服务器可以与客户端和其他服务器通信。 服务器到服务器和客户端到服务器发送序列化为< code>byte[]数组的< code >消息。每个< code >消息的第一个字节包含消息的大小,自然保证每个消息不包含超过< code>127 (2^8 -1)字节。您可以将服务器和客户端的消息发送视为循

  • 如果是在Javadocs中,我可能会忽略它。 熟悉API的人会看到类似的东西吗?

  • 我想知道为什么需要(又名reduce)第3个参数。对于那些不知道是什么的人,它的用法如下: 调用等同于: 还有可选第4个参数,它允许用任何其他操作替换加法。 我听说的一个基本原理是,如果你不需要加起来,而是乘一个向量的元素,我们需要其他的(非零)初始值: 但是为什么不像Python那样-为设置初始值,并使用从开始的范围。类似这样的事情: 这对任何行动都管用。为什么需要第三个参数?

  • 问题内容: 我的源数据在一个TSV文件中,包含6列和超过200万行。 这是我要完成的工作: 我需要读取此源文件中3列(3、4、5)中的数据 第五列是整数。我需要使用此整数值来复制行条目,并使用第三和第四列中的数据(按整数倍)。 我想将#2的输出写入CSV格式的输出文件。 以下是我想到的。 我的问题:这是一种有效的方法吗?尝试进行200万行时,它似乎很密集。 首先,我制作了一个示例选项卡单独的文件以

  • 问题内容: 我需要修改现有的APK,修改源,然后重新编译。 我可以使用dex2jar或apktool对其进行反编译,效果很好 从jar文件中,我可以获取Java源代码(使用jd-gui) 然后我可以修改Java文件 但是现在我想知道如何重新编译java文件并将它们放回jar文件中!(jar部分应该很简单,主要问题似乎是如何为Android重新编译Java文件) 我知道另一种解决方案是使用apkto

  • 问题内容: 我有一个pandas数据框。我想按升序打印其列之一的唯一值。这就是我的做法: 问题是我得到了输出。 问题答案: 从iterable中返回一个新的排序列表。 码 输出值