我有一段旧代码,用于在字符串中执行查找和替换标记。
它会收到from
和to
对的地图,对它们进行迭代,对于每个对,迭代目标字符串,使用{{1}查找from
},并将其替换为indexOf()
的值。它完成to
上的所有工作,最终返回StringBuffer
。
我用这一行替换了代码:String
我进行了一些比较性能测试
在比较replaceAll("[,. ]*", "");
次迭代时,我得到了这个:
旧代码:1287ms
新代码:4605ms
长3倍!
然后我尝试将其替换为1,000,000
的3次调用:
replace
replace(",", "");
replace(".", "");
这导致以下结果:
旧代码:1295
新代码:3524
2倍!
知道为什么replace(" ", "");
和replace
如此低效?我可以做些什么来加快速度吗?
编辑:感谢所有答案 - 主要问题确实replaceAll
没有做我想做的事情。将其更改为[,. ]*
几乎等于非基于正则表达式的解决方案的性能。
使用预编译的正则表达式有所帮助,但是很少。 (这是一个非常适用于我的问题的解决方案。
测试代码:
Replace string with Regex: [,. ]*
Replace string with Regex: [,. ]+
Replace string with Regex: [,. ]+ and Pre-Compiled Pattern
答案 0 :(得分:54)
虽然使用正则表达式会对某些性能产生影响,但它不应该那么糟糕。
请注意,使用String.replaceAll()
会编译正则表达式每次。\ n
您可以通过明确使用Pattern
对象来避免这种情况:
Pattern p = Pattern.compile("[,. ]+");
// repeat only the following part:
String output = p.matcher(input).replaceAll("");
另请注意,使用+
代替*
可以避免替换空字符串,因此也可能会加快处理速度。
答案 1 :(得分:7)
replace
和replaceAll
在内部使用正则表达式,在大多数情况下,与performance impact相比,会产生严重的StringUtils.replace(..)
。
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()));
}
另见Replace all occurrences of substring in a string - which is more efficient in Java?
答案 2 :(得分:3)
正如我发表评论[,。 ] *匹配空字符串“”。因此,字符之间的每个“空格”都与模式匹配。它仅在性能中被注意到,因为你用“”替换了很多“”。
尝试这样做:
Pattern p = Pattern.compile("[,. ]*");
System.out.println(p.matcher("Hello World").replaceAll("$$$");
它返回:
ħ$$$Ë$$$升$$$ö$$$$$$W¯¯$$$ö$$$ř$$$升$$$ d $$$!$$$
难怪“手工”这样做比较慢!你应该试试[,。 ] +
答案 3 :(得分:1)
说到replaceAll("[,. ]*", "")
,它并不是一个惊喜,因为它依赖于正则表达式。正则表达式引擎创建一个自动机,它在输入上运行。预计会有一些开销。
第二种方法(replace(",", "")...
)也在内部使用正则表达式。然而,这里使用Pattern.LITERAL
编译给定模式,因此正则表达式开销应该是可以忽略的。)在这种情况下,可能是由于Strings
是不可变的这一事实(无论你做了多少改变,你都会创建一个新的字符串),因此不如StringBuffers
那样有效地操作字符串。