I used to think that String.replace is faster than String.replaceAll because the latter uses Pattern regex and the former does not. But in fact there is no significant difference either in performance or implementation. This is it:
public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}
What’s the need to use Pattern here? I wrote a non-regex replace version
static String replace(String s, String target, String replacement) {
StringBuilder sb = new StringBuilder(s);
for (int i = 0; (i = sb.indexOf(target, i)) != -1; i += replacement.length()) {
sb.replace(i, i + target.length(), replacement);
}
return sb.toString();
}
and compared performance
public static void main(String args[]) throws Exception {
String s1 = "11112233211";
for (;;) {
long t0 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
// String s2 = s1.replace("11", "xxx");
String s2 = replace(s1, "11", "22");
}
System.out.println(System.currentTimeMillis() - t0);
}
}
Benchmarks: my version – 400ms; JDK version – 1700ms.
Is my test wrong or is String.replace really inefficient?
To give you some idea how inefficient String.replace is
From the source for Java 7 update 11.
AFAIK, the use of a Pattern and Matcher.quiteReplacement etc is an attempt to be clear rather than efficient. I suspect it dates back to when many internal libraries were written without performance considerations.
IMHO Java 7 has seen many internal libraries improve performance, in particular reduce needless object creation. This method is an obvious candidate for improvement.
You can improve the performance by doing the copy once, instead of trying to insert into an existing StringBuilder.
prints
Catching the Pattern and replace text helps a little, but not as much as having a custom routine to do the replace.