积累一个Java流,然后再处理它

积累一个Java流,然后再处理它,java,java-8,java-stream,reduce,collectors,Java,Java 8,Java Stream,Reduce,Collectors,我有一份文件,看起来如下: data.txt 100, "some text" 101, "more text" 102, "even more text" 我使用regex进行了处理,并返回了一个新的已处理文档,如下所示: Stream<String> lines = Files.lines(Paths.get(data.txt); Pattern regex = Pattern.compile("([\\d{1,3}]),(.*)"); List<MyClass>

我有一份文件,看起来如下:

data.txt

100, "some text"
101, "more text"
102, "even more text"
我使用regex进行了处理,并返回了一个新的已处理文档,如下所示:

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(),但没有成功,因为我实际上无法分割流

我想到Reduce来连接行,但我只连接行,不能减少并生成新的行流


有没有办法用Java8流解决这个问题?

这是
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);
用这个helper方法替换
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());
}
列表结果;
try(Scanner s=newscanner(path.get(“data.txt”)){
结果=匹配项(s,“(\\d{1,3}),\\s*\”([^\“]*)\”)
//MyClass(整型id,字符串文本)
.map(m->newmyclass(Integer.parseInt(m.group(1)),m.group(2)))
.collect(Collectors.toList());
}

在我看来,您的输入需要某种基本解析器,您不仅可以处理换行符,还可以处理引号转义。您的正则表达式中只有一个组。此外,您如何知道下一行是新ID还是前一个字符串的一部分?它们都有引号吗?如果字符串包含引号呢?您可能想知道为此使用CSV解析器。字符串可能包含引号,例如:101,“some”te xt和更多“text”102,“这是下一个文档”我需要使用lambdas以某种方式缓冲操作系统累积行?看起来您的输入可能是CSV文件。您考虑过使用CSV解析器吗?谢谢您的建议。我将尝试使用
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);
}
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());
}