Java String.replaceFirst性能与算法替换

Java String.replaceFirst性能与算法替换,java,Java,假设我想用“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);
}

通常最重要的事情是编写清晰简单的代码。就您的性能和需要维护代码的人员而言,第一个选项是最好的

如果你确定调用频繁,意味着你占用的时间太长,那么你可以考虑使用更复杂的编码。除非你已经衡量过它有多大的不同,否则我认为这只是一个猜测。在这种情况下,第二行可能是一个选项


顺便说一句,可能有更快的方法,例如使用StringBuilder,而不是根据上下文创建字符串。

通常最重要的是编写清晰简单的代码。就您的性能和需要维护代码的人员而言,第一个选项是最好的

如果你确定调用频繁,意味着你占用的时间太长,那么你可以考虑使用更复杂的编码。除非你已经衡量过它有多大的不同,否则我认为这只是一个猜测。在这种情况下,第二行可能是一个选项

顺便说一句,可能会有更快的方法,例如使用StringBuilder,而不是根据上下文创建字符串。

我编写了测试性能的代码。请使用适当的参数在您的机器上运行它以测试它。命令行接受一个从0到1的
double
,它表示测试输入与插入
“yyy”
子字符串的比率

方法论 生成长度为50、100、500、1000等的5000个随机字符串在5000个字符串中,有一定比例的字符串在随机位置插入序列“yyy”。(由于生成方法的原因,字符串将只包含
“yyy”
的一个实例(如果有),但我认为这不是问题)。对于(字符串长度)和(方法)的每个组合,我运行测试30次,并取平均值

测试了以下3种方法:

  • replaceFirst

    public static String replaceFirstApproach(String input) {
        return input.replaceFirst("yyy", "zzz");
    }
    
  • 子字符串

    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;
        }
    }
    
  • 结果 该程序在JVM7、Windows7上运行。这些数字是在微秒内处理一批5000个随机字符串的平均时间

    插入子字符串的0%“yyy”

    插入子字符串的50%“yyy”

    插入子字符串的100%“yyy”

    长度| 50 100 500 1000 5000 --------------|------------------------------------------------------- 替换第一| 22984 31302 103640 192179 892965 子串| 7846 11494 37093 58544 258356 StringBuilder | 11113 24499 66164 121784 592664 结论 使用
    replaceFirst
    的方法总是最慢的。当未找到
    “yyy”
    子字符串时,其速度比其他两种方法慢3-10倍。当可以找到
    “yyy”
    子字符串时,它仍然比
    子字符串方法慢3倍,比
    StringBuilder方法慢1.5倍

    当可以找到
    “yyy”
    子字符串且字符串很长时,将字符串与
    +
    子字符串
    连接的方法比
    StringBuilder
    快2倍

    不过,这里的用例是相当本地化的。尽管
    子字符串
    方法速度更快,但除非您进行密集的字符串处理,否则所获得的收益微不足道。

    。请使用适当的参数在您的机器上运行它以测试它。命令行接受一个从0到1的
    double
    ,它表示测试输入与插入
    “yyy”
    子字符串的比率

    方法论 生成长度为50、100、500、1000等的5000个随机字符串在5000个字符串中,有一定比例的字符串在随机位置插入序列“yyy”。(由于生成方法的原因,字符串将只包含
    “yyy”
    的一个实例(如果有),但我认为这不是问题)。对于(字符串长度)和(方法)的每个组合,我运行测试30次,并取平均值

    测试了以下3种方法:

  • replaceFirst

    public static String replaceFirstApproach(String input) {
        return input.replaceFirst("yyy", "zzz");
    }
    
  • 子字符串

    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;
        }
    }
    
  • 结果 该程序在JVM7、Windows7上运行。这些数字是在微秒内处理一批5000个随机字符串的平均时间

    插入子字符串的0%“yyy”

    插入子字符串的50%“yyy”

    插入子字符串的100%“yyy”

    长度| 50 100 500 1000 5000 --------------|------------------------------------------------------- 替换第一| 22984 31302 103640 192179 892965 子串| 7846 11494 37093 58544 258356 StringBuilder | 11113 24499 66164 121784 592664 结论 使用
    replaceFirst
    的方法总是最慢的。当未找到
    “yyy”
    子字符串时,其速度比其他两种方法慢3-10倍。当可以找到
    “yyy”
    子字符串时,它仍然比
    子字符串方法慢3倍,比
    StringBuilder方法慢1.5倍

    方法 Length | 50 100 500 1000 5000 --------------|------------------------------------------------------- replaceFirst | 20318 28387 95967 176051 845799 substring | 6840 9940 27469 47218 198464 StringBuilder | 8794 13272 50498 94644 470656 Length | 50 100 500 1000 5000 --------------|------------------------------------------------------- replaceFirst | 22984 31302 103640 192179 892965 substring | 7846 11494 37093 58544 258356 StringBuilder | 11113 24499 66164 121784 592664