我正在尝试制作一个流版本的StringTokenizer,但是我在正确终止流时遇到了一些问题。
public Stream<String> tokenize(String text) {
StringTokenizer tokenizer = new StringTokenizer(text);
return Stream.generate(tokenizer::nextToken)
.takeWhile(s -> tokenizer.hasMoreTokens());
}但是,当我运行这段代码时,最后一个令牌丢失了:
Stream<String> tokens = new DefaultTokenizer().tokenize(" a b c d\te f\n");
tokens.forEach(System.out::println);在以下方面的成果:
a
b
c
d
e我尝试过像这样使用Stream.iterate:Stream.iterate(tokenizer.nextToken(), s -> tokenizer.hasMoreTokens(), s -> tokenizer.nextToken()),但是结果是一样的。
显然,谓词hasMoreTokens一通过,我就会终止流,但是在那之后我需要使用最后一个元素,在获得最后一个元素之后,我如何终止?
发布于 2021-02-14 11:43:59
就像在所有其他答案中一样,我会避免使用StringTokenizer。
为了避免处理整个字符串,可以使用Pattern.splitAsStream(String)而不是通常的split方法。
因此,在您的例子中,类似于使用StringTokenizer的结果应该是相似的。(字符串为split at any (non-empty) sequence of white-space)
Pattern.compile("\\s+").splitAsStream(text)发布于 2021-02-14 11:13:28
StringTokenizer是一个遗留类,您可能不这么认为。编辑:我从这个答案中删除了我的解决方案,因为the answer by magicmn中的解决方案要好得多。
编辑:您的代码出了什么问题?您尝试过:
Stream.iterate(tokenizer.nextToken(), s -> tokenizer.hasMoreTokens(), s -> tokenizer.nextToken())这里发生的事情是,流使用s -> tokenizer.hasMoreTokens()来确定是否将当前令牌s包含在流中。对于最后一个令牌f,它显然已经从StringTokenizer中提取了它,因此StringTokenizer返回false for hasMoreTokens(),而f不包含在流中。
发布于 2021-02-14 12:14:56
您的供应商在结束时返回null和takeWhile(nonNull)的小调整将允许您继续使用Tokeniser:
public Stream<String> tokenize(String text) {
StringTokenizer tokenizer = new StringTokenizer(text);
return Stream.generate(() -> tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null)
.takeWhile(Objects::nonNull);
}https://stackoverflow.com/questions/66194579
复制相似问题