问题描述
这可能是一个非常简单的问题,也可能是一个重复的问题(尽管我确实事先进行了检查),但是在String.replaceAll()
或matcher.replaceAll()
循环中使用时,它便宜吗?
有人告诉我
Pattern regexPattern = Pattern.compile("[^a-zA-Z0-9]");
Matcher matcher;
String thisWord;
while (Scanner.hasNext()) {
matcher = regexPattern.matcher(Scanner.next());
thisWord = matcher.replaceAll("");
...
}
更好,因为您只需要编译一次正则表达式,我认为
的好处String thisWord;
while (Scanner.hasNext()) {
thisWord = Scanner.next().replaceAll("[^a-zA-Z0-9]","");
...
}
远远超过了matcher
方法,因为不必每次都初始化matcher
。 (我知道matcher
已经存在,因此您无需重新创建它。)
有人可以解释我的推理是错误的吗?我误解了Pattern.matcher()
的作用吗?
解决方法
在OpenJDK中,String.replaceAll的定义如下:
public String replaceAll(String regex,String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
因此,至少在该实现中,它不会比仅编译一次模式并使用Matcher.replaceAll提供更好的性能。
可能还有其他JDK实现,其中String.replaceAll的实现方式有所不同,但是如果它在任何方面都比Matcher.replaceAll更好,我会感到非常惊讶。
[…],因为不必每次都初始化匹配器。 (我知道匹配器已经存在,因此您无需重新创建它。)
我认为您在这里有误会。您确实确实在每次循环迭代时都创建了一个新的Matcher实例;但这很便宜,无需考虑性能。
顺便说一句,如果您不需要变量,实际上并不需要一个单独的“ matcher”变量。编写以下内容,您将获得完全相同的行为和性能:
thisWord = regexPattern.matcher(Scanner.next()).replaceAll("");
,
如果重置相同的匹配器,则有一种更有效的方法,这样就不会在循环内的每种情况下都重新生成该匹配器,它会复制与Pattern结构有关的大多数相同信息。
Pattern regexPattern = Pattern.compile("[^a-zA-Z0-9]");
Matcher matcher = regexPattern.matcher("");
String thisWord;
while (Scanner.hasNext()) {
matcher = matcher.reset(Scanner.next());
thisWord = matcher.replaceAll("");
// ...
}
在循环regexPattern.matcher("")
之外创建匹配器会产生一次性费用,但是对matcher.reset(xxx)
的调用会更快,因为它们会重用该匹配器,而不是重新生成新的匹配器实例每一次。这样可以减少所需的GC数量。