这不是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:
如何包含最后一个空行?
答案 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分割并检查最后一个条目似乎更具可读性。