String.replaceAll()和Matcher.replaceAll()(在由Regex.Pattern创建的Matcher对象上)在性能方面是否存在已知的差异?
另外,它们之间的高级API的差异是什么?(不变性、处理NULL值、处理空字符串等)
String.replaceAll()和Matcher.replaceAll()(在由Regex.Pattern创建的Matcher对象上)在性能方面是否存在已知的差异?
另外,它们之间的高级API的差异是什么?(不变性、处理NULL值、处理空字符串等)
String.replaceAll
文档的说明,对该方法进行调用有以下内容:
以
str.replaceAll(regex, repl)
形式调用该方法会产生与表达式相同的结果因此,可以预期调用Pattern.compile(regex).matcher(str).replaceAll(repl)
String.replaceAll
和显式创建Matcher
和Pattern
之间的性能应该是相同的。 编辑 正如在评论中指出的那样,对于从String
或Matcher
进行单个replaceAll
调用来说,不存在性能差异。然而,如果需要执行多个replaceAll
调用,则可以保留已编译的Pattern
,以便不必每次都执行相对昂贵的正则表达式模式编译。
String.replaceAll()
的源代码:
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
必须先编译模式——如果你要在短字符串上多次运行相同的模式,那么通过重复使用已编译的 Pattern,性能会更好。
主要区别在于如果你保留用来产生 Matcher
的 Pattern
,你就可以避免每次使用正则表达式时重新编译。通过使用 String
,你无法像这样“缓存”正则表达式。
如果每次都有不同的正则表达式,那么使用 String
类的 replaceAll
就可以了。但如果你要对许多字符串应用相同的正则表达式,创建一个 Pattern
并重复使用它。
不可变性/线程安全性:编译的模式是不可变的,匹配器是可变的。(参见Java Regex是否线程安全?)
处理空字符串:replaceAll应该优雅地处理空字符串(它不会匹配空输入字符串模式)
制作咖啡等:据我所知,String、Pattern和Matcher都没有相关API功能。
编辑:关于处理null值,String和Pattern的文档没有明确说明,但我怀疑它们会抛出NullPointerException,因为它们需要一个字符串。
String.replaceAll
的实现告诉您所需了解的一切:return Pattern.compile(regex).matcher(this).replaceAll(replacement);
Pattern.compile
更有效率。如果有缓存,它将是一个小的效率节省 - 如果没有,它可能会是一个大的节省。Matcher m = Pattern.compile(regex).matcher("");
for (String s : targets)
{
System.out.println(m.reset(s).replaceAll(repl));
}
Matcher::replaceAll
和String::replaceAll
之间的另一个区别也是编译自己的Pattern
的原因。当您自己编译Pattern
时,有一些选项可以修改正则表达式的应用方式。例如:Pattern myPattern = Pattern.compile(myRegex, Pattern.CASE_INSENSITIVE);
Matcher
在调用 Matcher::replaceAll
时会应用您设置的所有标志。
还有其他标志可以设置。主要是想指出 Pattern
和 Matcher
API 有很多选项,这是超越简单的 String::replaceAll
的主要原因。
Pattern.compile(...).matcher("ignored input")
创建它,然后使用theMatcher.reset(theString).replaceAll(...)
进行操作。 - aliteralmind