String.replaceAll比自己完成工作慢得多

我有一段旧代码,用于在字符串中执行查找和替换标记。

它接收fromto的映射,迭代它们,对于每个对,迭代目标字符串,查找from使用indexOf() ,并用to的值替换它。 它完成StringBuffer上的所有工作,最终返回一个String

我用这一行替换了那段代码: replaceAll("[,. ]*", "");
我进行了一些比较性能测试。
当比较1,000,000次迭代时,我得到了这个:

旧代码:1287ms
新代码:4605ms

3倍长!

然后我尝试用3次调用替换它来replace
replace(",", "");
replace(".", "");
replace(" ", "");

结果产生了以下结果:

旧代码:1295
新代码:3524

2倍长!

任何想法为什么replacereplace都是如此低效? 我能做些什么来加快速度吗?


编辑:感谢所有答案 – 主要问题确实是[,. ]* [,. ]*没有做我想做的事。 将其改为[,. ]+ [,. ]+几乎等于非基于正则表达式的解决方案的性能。 使用预编译的正则表达式有所帮助,但是很少。 (这是一个非常适合我的问题的解决方案。

测试代码:
用正则表达式替换字符串:[,。 ] *
用正则表达式替换字符串:[,。 ] +
用正则表达式替换字符串:[,。 ] +和预编译模式

虽然使用正则表达式可以产生一些性能影响,但它不应该那么糟糕。

请注意, 每次调用时,使用String.replaceAll()都会编译正则表达式。

您可以通过显式使用Pattern对象来避免这种情况:

 Pattern p = Pattern.compile("[,. ]+"); // repeat only the following part: String output = p.matcher(input).replaceAll(""); 

另请注意,使用+而不是*可以避免替换空字符串,因此也可能加快进程。

replacereplaceAll在内部使用正则表达式 ,与大多数情况下相比,例如StringUtils.replace(..)会产生严重的性能影响 。

String.replaceAll()

 public String replaceAll(String regex, String replacement) { return Pattern.compile(regex).matcher(this ).replaceAll( replacement); } 

String.replace()使用下面的Pattern.compile。

 public String replace(CharSequence target, CharSequence replacement) { return Pattern.compile(target.toString(), Pattern.LITERAL) .matcher(this ).replaceAll( Matcher.quoteReplacement(replacement.toString())); } 

另请参阅替换字符串中所有出现的子字符串 – 这在Java中更有效吗?

正如我发表评论[,。 ] *匹配空字符串“”。 因此,字符之间的每个“空格”都与模式匹配。 它仅在性能中被注意到,因为你用“”代替了很多“”。

试着这样做:

 Pattern p = Pattern.compile("[,. ]*"); System.out.println(p.matcher("Hello World").replaceAll("$$$"); 

它返回:

^ h $$$è$$$升$$$Ø$$$$$$W¯¯$$$Ø$$$ [R $$$升$$$ d $$$!$$$

难怪“手工”这样做比较慢! 你应该试试[,。 ] +

当涉及到replaceAll("[,. ]*", "")时,由于它依赖于正则表达式,因此并不是一个惊喜。 正则表达式引擎创建一个自动机,它在输入上运行。 预计会有一些开销。

第二种方法( replace(",", "")... )也在内部使用正则表达式。 然而,这里使用Pattern.LITERAL编译给定的模式,因此正则表达式开销应该是可以忽略的。)在这种情况下,可能是因为Strings是不可变的(不管你做了多少改动,你将创建一个新的字符串)和因此不如StringBuffers那样有效地操作字符串。