假设我想用“zzz”替换字符串中第一次出现的“yyy”。String.replaceFirst 似乎是一个完美的解决方案
str = str.repaceFirst("yyy", "zzz");
但是有性能问题吗?以下解决方案在性能方面有什么不同吗?
int i = s.indexOf("yyy");
if (i != -1) {
str = str.substring(0, i) + "zzz" + s.substring(i + 3);
}
假设我想用“zzz”替换字符串中第一次出现的“yyy”。String.replaceFirst 似乎是一个完美的解决方案
str = str.repaceFirst("yyy", "zzz");
但是有性能问题吗?以下解决方案在性能方面有什么不同吗?
int i = s.indexOf("yyy");
if (i != -1) {
str = str.substring(0, i) + "zzz" + s.substring(i + 3);
}
我写了一些代码来测试性能。请使用适当的参数在您的盒子上运行它来测试它。命令行接受一个double
从 0 到 1 的值,表示测试输入与插入"yyy"
子字符串的比率。
生成5000个长度为50、100、500、1000等的随机字符串。5000 个字符串中的一部分在随机位置插入序列“yyy” 。(由于生成方法,字符串将只包含一个实例,"yyy"
如果有的话,但我认为这不是问题)。对于(字符串长度)和(方法)的每种组合,我运行测试30次并取平均值。
测试了以下 3 种方法:
replaceFirst
:
public static String replaceFirstApproach(String input) {
return input.replaceFirst("yyy", "zzz");
}
substring
:
public static String substringApproach(String input) {
int i = input.indexOf("yyy");
if (i != -1) {
input = input.substring(0, i) + "zzz" + input.substring(i + 3);
}
return input;
}
用于StringBuilder
构造输出字符串:
public static String appendStringBuilder(String input) {
int i = input.indexOf("yyy");
if (i != -1) {
StringBuilder output = new StringBuilder(input.length());
output.append(input, 0, i).append("zzz").append(input, i + 3, input.length());
return output.toString();
} else {
return input;
}
}
该程序在 JVM 7、Windows 7 上运行。这些数字是处理 1 批 5000 个随机字符串的平均时间(以微秒为单位)。
在插入子字符串的0%处"yyy"
长度 | 50 100 500 1000 5000 --------------|------------------------------------ -------------------- 替换优先 | 17389 22718 74194 137285 629438 子串 | 4429 7246 13421 18069 78920 字符串生成器 | 4604 5615 11509 19093 79366
插入子字符串的25%"yyy"
长度 | 50 100 500 1000 5000 --------------|------------------------------------ -------------------- 替换优先 | 18531 24959 78211 146956 692992 子串 | 5250 6764 18994 27959 113805 字符串生成器 | 5768 8609 23857 45789 205580
插入子字符串的50%"yyy"
长度 | 50 100 500 1000 5000 --------------|------------------------------------ -------------------- 替换优先 | 19833 27648 90932 162558 760558 子串 | 6007 8848 21909 37415 154959 字符串生成器 | 7075 12095 37765 70038 327171
插入子字符串的75%"yyy"
长度 | 50 100 500 1000 5000 --------------|------------------------------------ -------------------- 替换优先 | 20318 28387 95967 176051 845799 子串 | 6840 9940 27469 47218 198464 字符串生成器 | 8794 13272 50498 94644 470656
插入子字符串的100%"yyy"
长度 | 50 100 500 1000 5000 --------------|------------------------------------ -------------------- 替换优先 | 22984 31302 103640 192179 892965 子串 | 7846 11494 37093 58544 258356 字符串生成器 | 11113 24499 66164 121784 592664
的方法replaceFirst
总是最慢的。当"yyy"
未找到子字符串时,它比其他 2 种方法慢 3-10 倍。当"yyy"
可以找到子字符串时,它仍然比substring
接近慢 3 倍,StringBuilder
接近 1.5 倍。
+
使用and连接字符串的方法比可以找到子字符串且字符串很长时substring
快 2 倍。StringBuilder
"yyy"
不过,这里的用例非常本地化。尽管该substring
方法更快,但除非您进行密集的字符串处理,否则收益微不足道。
通常最重要的是编写清晰简单的代码。就您的性能和必须维护代码的人而言,第一个选项是最好的。
如果您确定这被调用的频率足够高并且意味着您花费的时间太长,那么您可能会考虑使用更复杂的编码。除非你测量过它有多大的不同,否则我认为这只是一个猜测。在这种情况下,第二行可能是一个选项。
顺便说一句,可能有更快的方法,例如使用 StringBuilder 而不是根据您的上下文创建 String 。