如何在Pattern.compile(“ \\ R”)。splitAsStream(input)中包含结尾的空字符串?

时间:2019-01-15 11:34:33

标签: java regex newline

这不是Java String split removed empty values的重复项,它处理split()方法返回一个新数组。在这种情况下,我想避免使用数组

我通过变通办法解决了这个问题,下面将其发布为我问题的可能解决方案。

我的目标是处理包括空字符串在内的所有行,例如以下示例:

String input = "foo\nbar\n\n\nzul\n\n\n";
Pattern NEWLINE = Pattern.compile("\\R");
int [] count = {1};
NEWLINE
    .splitAsStream(input)
    .forEach(line -> System.out.println(count[0]++ + ": " + line));

产生:

1: foo
2: baz
3: 
4: 
5: zul

但是,它丢失了:

6: 
7:

如何包含最后一个空行?

3 个答案:

答案 0 :(得分:2)

您可以使用a lookahead (?=(\\R))来确保不消耗\\R分隔符,然后使用String.trim()自己将其删除。

String input = "foo\nbar\n\n\nzul\n\n\n";
Pattern NEWLINE = Pattern.compile("(?=(\\R))");
int[] count = {1};
NEWLINE.splitAsStream(input)
       .map(String::trim)
       .forEach(line -> System.out.println(count[0]++ + ": " + line));

但是,最后一个""之后的\n长度匹配为零。<​​/ p>

1: foo
2: bar
3: 
4: 
5: zul
6: 
7: 
8: 

答案 1 :(得分:1)

作为替代方案,您可以自己实现与splitAsStream()等效的方法,该方法包括尾随空字符串,并且仍然避免实例化数组,例如:

static Stream<String> splitAsStream(Pattern p, CharSequence input) {
    Spliterator<String> iter = new Spliterators.AbstractSpliterator<String>(
        Long.MAX_VALUE,
        Spliterator.ORDERED | Spliterator.SIZED
    ) {
        int index = 0;
        final Matcher m = p.matcher(input);

        @Override
        public boolean tryAdvance(Consumer<? super String> action) {
            while(m.find()) {
                if (index != 0 || index != m.start() || m.start() != m.end()) {
                    action.accept(input.subSequence(index, m.start()).toString());
                    index = m.end();
                    return true;
                }
            }
            if(index < input.length()) {
                // Add remaining segment
                action.accept(input.subSequence(index, input.length()).toString());
                index = input.length();
                return true;
            } else {
                return false;
            }
        }
    };
    return StreamSupport.stream(iter, false);
}

答案 2 :(得分:1)

java 9 on can use Matcher.results() yielding a Stream<MatchResult>

Pattern.compile("(.*)\\R").matcher(input)
    .results(mr -> System.out.println(count[0]++ + ": " + mr.group(1)));

这保证了最后的“行”也具有终止\n。 “ .... \ nabc”将放弃最后一个abc。

为此,我认为以下操作应该起作用(请注意group()),先行使用,并要求$最后至少有一个字符.

Pattern.compile(".*(?=\\R)|.$)").matcher(input)
    .results(mr -> System.out.println(count[0]++ + ": " + mr.group()));

用-1分割并检查最后一个条目似乎更具可读性。