我以前认为String.replace比String.replaceAll更快,因为后者使用Pattern正则表达式而前者不使用.但事实上,在性能或实施方面没有显着差异.就是这个:
public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}
Run Code Online (Sandbox Code Playgroud)
这里有什么需要使用Pattern?我写了一个非正则表达式替换版本
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();
}
Run Code Online (Sandbox Code Playgroud)
并比较了表现
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);
}
}
Run Code Online (Sandbox Code Playgroud)
基准:我的版本 - 400ms; JDK版本 - 1700ms.
我的测试是错误的还是String.replace真的效率低下?
Pet*_*rey 11
让你知道String.replace是多么低效
来自Java 7更新11的源代码.
public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}
Run Code Online (Sandbox Code Playgroud)
AFAIK,使用Pattern和Matcher.quiteReplacement等是尝试清晰而不是有效.我怀疑它可以追溯到许多内部库是在没有性能考虑的情况下编写的.
恕我直言Java 7已经看到许多内部库提高了性能,特别是减少了不必要的对象创建.这种方法显然是改进的候选者.
您可以通过执行一次复制来提高性能,而不是尝试插入现有的StringBuilder.
static String replace2(String s, String target, String replacement) {
StringBuilder sb = null;
int start = 0;
for (int i; (i = s.indexOf(target, start)) != -1; ) {
if (sb == null) sb = new StringBuilder();
sb.append(s, start, i);
sb.append(replacement);
start = i + target.length();
}
if (sb == null) return s;
sb.append(s, start, s.length());
return sb.toString();
}
public static void main(String... ignored) {
String s1 = "11112233211";
for (; ; ) {
timeReplace(s1);
timeReplace2(s1);
timeStringReplaceRefactored(s1);
timeStringReplace(s1);
}
}
private static void timeStringReplace(String s1) {
long start0 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
String s2 = s1.replace("11", "xxx");
if (s2.length() <= s1.length()) throw new AssertionError();
}
System.out.printf("String.replace %,d ns avg%n", System.currentTimeMillis() - start0);
}
private static void timeStringReplaceRefactored(String s1) {
long start0 = System.currentTimeMillis();
Pattern compile = Pattern.compile("11", Pattern.LITERAL);
String xxx = Matcher.quoteReplacement("xxx");
for (int i = 0; i < 1000000; i++) {
String s2 = compile.matcher(s1).replaceAll(xxx);
if (s2.length() <= s1.length()) throw new AssertionError();
}
System.out.printf("String.replace %,d ns avg (Refactored)%n", System.currentTimeMillis() - start0);
}
private static void timeReplace(String s1) {
long start0 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
String s2 = replace(s1, "11", "xxx");
if (s2.length() <= s1.length()) throw new AssertionError();
}
System.out.printf("Replace %,d ns avg%n", System.currentTimeMillis() - start0);
}
private static void timeReplace2(String s1) {
long start0 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
String s2 = replace2(s1, "11", "xxx");
if (s2.length() <= s1.length()) throw new AssertionError();
}
System.out.printf("My replace %,d ns avg%n", System.currentTimeMillis() - start0);
}
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();
}
Run Code Online (Sandbox Code Playgroud)
版画
Replace 177 ns avg
My replace 108 ns avg
String.replace 436 ns avg (Refactored)
String.replace 598 ns avg
Run Code Online (Sandbox Code Playgroud)
捕获模式并替换文本有一点帮助,但不如使用自定义例程进行替换.