Suv*_*apa 44 java regex string replaceall
非常简单的问题,但这是来自一个C/C++人进入Java的复杂性.
我知道我可以启动jUnit和我自己的一些性能测试来得到答案; 但我只是想知道这是否在那里.
在性能方面,String.replaceAll()和Matcher.replaceAll()(从Regex.Pattern创建的Matcher对象)之间是否存在已知差异?
此外,两者之间的高级API是什么区别?(不变性,处理NULL,处理空字符串,制作咖啡等)
coo*_*ird 75
根据文档String.replaceAll,它有关于调用方法的以下内容:
调用此表单的方法会
str.replaceAll(regex, repl)产生与表达式完全相同的结果Run Code Online (Sandbox Code Playgroud)Pattern.compile(regex).matcher(str).replaceAll(repl)
因此,可以预期调用之间的性能String.replaceAll,以及显式创建Matcher和Pattern应该是相同的.
编辑
正如在评论中指出的那样,对于replaceAll来自String或的单个调用,性能差异是不存在的Matcher,但是,如果需要执行多次调用replaceAll,人们会认为保持编译是有益的.Pattern因此,不必每次都执行相对昂贵的正则表达式模式编译.
Mic*_*rdt 23
源代码String.replaceAll():
public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}
Run Code Online (Sandbox Code Playgroud)
它必须首先编译模式 - 如果你要在短字符串上使用相同的模式多次运行它,如果你重用一个已编译的模式,性能会好得多.
主要的区别在于,如果你持有Pattern用于生成的Matcher,你可以避免每次使用它时重新编译正则表达式.经历过String,你没有像这样"缓存"的能力.
如果你每次都有不同的正则表达式,那么使用这个String类replaceAll很好.如果要将相同的正则表达式应用于多个字符串,请创建一个Pattern并重复使用它.
不变性/线程安全:编译模式是不可变的,匹配器不是.(请参阅Java Regex线程安全吗?)
处理空字符串:replaceAll应该优雅地处理空字符串(它不匹配空输入字符串模式)
制作咖啡等:最后我听说,String和Pattern以及Matcher都没有任何API功能.
编辑:至于处理NULL,String和Pattern的文档没有明确说明,但我怀疑他们会抛出一个NullPointerException,因为他们期望一个String.
的实现String.replaceAll告诉你你需要知道的一切:
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
Run Code Online (Sandbox Code Playgroud)
(而且文档也说了同样的话。)
虽然我还没有检查缓存,我当然希望在编译模式一次,并保持静态引用,这将是比调用更有效地Pattern.compile使用相同的模式各一次。如果有缓存,这将是一个小的效率节省 - 如果没有,它可能是一个大的。
不同之处在于 String.replaceAll() 每次调用时都会编译正则表达式。.NET 的静态 Regex.Replace() 方法没有等效项,它会自动缓存已编译的正则表达式。通常,replaceAll() 是您只执行一次的操作,但是如果您要使用相同的正则表达式重复调用它,尤其是在循环中,您应该创建一个 Pattern 对象并使用 Matcher 方法。
您也可以提前创建 Matcher,并使用其 reset() 方法为每次使用重新定位它:
Matcher m = Pattern.compile(regex).matcher("");
for (String s : targets)
{
System.out.println(m.reset(s).replaceAll(repl));
}
Run Code Online (Sandbox Code Playgroud)
当然,重用 Matcher 的性能优势远不如重用 Pattern。