什么情况下用+运算符进行字符串连接比调用StringBuilder对象的append方法连接字符串性能更好?

java技术交流QQ群:83753349


经常在网上看到或者在周围听到有人说字符串拼接不要直接用 String 相加, StringBuilder 的效率要比 String 直接相加拼接要高。还有人常说, StringBuffer 是同步的(线程安全的), StringBuilder 不是线程安全的,同步带来了性能消耗,那么 String 、 StringBuilder 、 StringBuffer 这三者的效率到底有多大的差距呢?

Talk is cheap, show me the code!

   
public class StringCatTest {
    public static void main(String[] args) {
        printResult(100);
        System.out.println("***********************************************");
        printResult(1000);
        System.out.println("***********************************************");
        printResult(10000);
        System.out.println("***********************************************");
        printResult(100000);
        System.out.println("***********************************************");
        printResult(1000000);
        System.out.println("***********************************************");
        printResult(10000000);



    }
    public static void printResult(long loopCount) {
        System.out.println("loopCount:" + loopCount);
        stringCat(loopCount);
        stringBuilderAppend(loopCount);
        stringBufferAppend(loopCount);
    }
    public static long stringCat(long loopCount) {
        long beginTime = System.currentTimeMillis();
        String str = "hello,world!";
        String result = "";

        for (int i = 0; i < loopCount; i++) {
            result += str;
        }
        long consumeTime = System.currentTimeMillis()-beginTime;
        System.out.println("String cat time:" + consumeTime);
        return consumeTime;
    }

    public static long stringBuilderAppend(long loopCount) {
        long beginTime = System.currentTimeMillis();
        String str = "hello, world!";
        String result = "";
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < loopCount; i++) {
            stringBuilder.append(str);
        }
        result = stringBuilder.toString();
        long consumeTime = System.currentTimeMillis()-beginTime;
        System.out.println("StringBuilder append time:" + consumeTime);
        return consumeTime;

    }

    public static long stringBufferAppend(long loopCount) {
        long beginTime = System.currentTimeMillis();
        String str = "hello, world!";
        String result = "";
        StringBuffer stringBuffer = new StringBuffer();

        for (int i = 0; i < loopCount; i++) {
            stringBuffer.append(str);
        }
        result = stringBuffer.toString();
        long consumeTime = System.currentTimeMillis()-beginTime;
        System.out.println("StringBuffer append time:" + consumeTime);
        return consumeTime;
    }

}

很简单的代码,通过调整循环次数的大小,来打印出三种字符串连接所花费的时间:


从上面的输出打印我们可以明显地看出,在循环次数次数较小(比如说小于100)时,三者的时间效率差不多,当随着循环次数的增加,对比效果发生了显著的变化。

我们平时用字符串直接相加作连接,也可以,但在循环内部最好还是用 StringBuilder 作字符串的连接,其实在循环次数较小的情况下我们也可以用 String 直接来相加连接,但有时我们根本不能确定循环次数的大小,所以最好还是老老实实的用 StringBuilder 。

为什么 StringBuilder 和 String 直接连接有如此大的性能差异呢,下面我们来分析一下:

        String str = "hello,world!";
        String result = "";

        for (int i = 0; i < loopCount; i++) {
            result += str;
        }

编译器最终会把上面的代码编译为类似下面的代码:

        String str = "hello,world!";
        String result = "";

        for (int i = 0; i < loopCount; i++) {
            result = new StringBuilder(result).append(str).toString();
        }

当执行 new StringBuilder(result) 时,构造方法 StringBuilder 会复制 result 中的所有字符到新建的 StringBuilder 中。每次循环都需要创建一个 StringBuilder 对象(创建对象时需要耗费时间和内存),随着循环次数的增大, result 字符串就会越来越长,把 result 中的字符复制到新建的 StringBuilder 中花费的时间也就越长,而且 StringBuilder(result).append(str).toString() 会创建一个临时的字符串,随着循环次数的增加,这个操作花费的时间也会越来越长。总之,随着循环变量 i 的增大,每次循环会变得越来越慢。

从上面的输出可以看出当循环次数增大后, StringBuilder 的效率要比 StringBuffer要好一些。

下面是 StringBuilder 和 StringBuffer 两者之间的一个对比:


当循环次数增大到 1000w后,两者才有了明显的差异, StringBuilder 的效率要比 StringBuffer 的要高一些。

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值