累积Java流,然后才对其进行处理
我有一个类似于以下内容的文档:
data.txt中
100, "some text" 101, "more text" 102, "even more text"
我使用正则表达式处理它并返回一个新的处理文档如下:
Stream lines = Files.lines(Paths.get(data.txt); Pattern regex = Pattern.compile("([\\d{1,3}]),(.*)"); List 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(),但没有成功,因为我实际上无法拆分流。
Reduce会让人联想到连接行,但我会连接只是行,我不能减少并生成一个新的行流。
任何想法如何用java 8流解决这个问题?
这是java.util.Scanner
的工作。 随着即将推出的Java 9,你会写:
List 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);
但是由于在Java 8下不存在生成findAll
的Stream
,我们需要一个帮助方法:
private static Stream matches(Scanner s, String pattern) { Pattern compiled=Pattern.compile(pattern); return StreamSupport.stream( new Spliterators.AbstractSpliterator (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 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()); }