【发布时间】:2019-08-05 20:16:48
【问题描述】:
我遇到了流的dropWhile 或takeWhile 方法的问题,因为拆分器以奇数或偶数的特定模式跳过部分文本。应该如何处理文本的所有部分?
我的方法在这里:
void read(Path filePath) {
try {
Stream<String> lines = Files.lines(filePath);
while (true) {
Spliterator<String> spliterator = lines.dropWhile(line -> !line.startsWith("FAYSAL:")).spliterator();
Stream<String> portion = fetchNextPortion(spliterator);
if(spliterator.estimateSize() == 0)
break;
portion .forEach(System.out::println);
lines = StreamSupport.stream(spliterator, false);
}
lines.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
private Stream<String> fetchNextPortion(Spliterator<String> spliterator) {
return StreamSupport.stream(spliterator, false)
.filter(this::isValidReportName)
.peek(System.out::println)
.findFirst()
.map( first -> Stream.concat(Stream.of(first),
StreamSupport.stream(spliterator, false).takeWhile(line -> !line.startsWith("FAYSAL:")))).orElse(Stream.empty());
}
示例输入是:
FAYSAL: 1
Some text here
Some text here
FAYSAL: 2
Some text here
Some text here
FAYSAL: 3
Some text here
Some text here
FAYSAL: 4
Some text here
Some text here
它将跳过 FAYSAL: 2 和 FAYSAL: 4
【问题讨论】:
-
dropWhile和takeWhile读起来好像会导致同样的奇怪行为,那么为什么不使用filter? -
@Tom
filter将产生一个新问题。它将过滤每一行,并跳过两个标签之间的行。 -
不保证您可以在处理基于它的 Stream 之后重用
Spliterator。最值得注意的是,被filter拒绝的行不可避免地已经被消耗掉了。但原则上,任何数量的后续元素都可能已经被消耗掉了。你应该描述你真正想做的事情(另见What is the XY problem?)。但它看起来像是this 的变体,简而言之:如果要处理多行工件,请使用Scanner。 -
我已经解释过了,你正在从一个分离器构造多个流,这根本没有保证的行为。所以用这种方法,是无解的。我还解释了当前实现的行为。使用
takeWhile(line -> !line.startsWith("FAYSAL:")),您已经在使用以"FAYSAL:"开头的下一行。该流将按请求停止处理,但它必须从拆分器中获取该行,以发现它不匹配。所以从同一个拆分器构造的下一个流看不到那条线。 -
如果我正确理解您的问题,您可能想看看my answer to a similar question。那个人也在寻找一种将流切割成块的方法。
标签: java stream java-stream java-9 spliterator