java基础-java常用类-String、StringBuffer、StringBuilder-String类(3)

Java常用类之String、StringBuilder、StringBuffer

对比String,StringBuffer,StringBuilder三者的效率

前提在单线程,同步执行,先执行StringBuffer.append,再执行StringBuilder.append场景,各循环2000次添加字符下

执行java环境jdk1.8

代码:

public class CompareTest {
    public static void main(String[] args) {

        //初始设置
        long startTime = 0L;
        long endTime = 0L;
        String text = "";
        StringBuffer buffer = new StringBuffer("");
        StringBuilder builder = new StringBuilder("");
        //开始对比
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            buffer.append(String.valueOf(i));
        }
        endTime = System.currentTimeMillis();
        log.info("StringBuffer的执行时间:{}", (endTime - startTime));
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            builder.append(String.valueOf(i));
        }
        endTime = System.currentTimeMillis();
        log.info("StringBuilder的执行时间:{}", (endTime - startTime));
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 20000; i++) {
            text += i;
        }
        endTime = System.currentTimeMillis();
        log.info("String的执行时间:{}", (endTime - startTime));

    }
}

执行结果

10:32:19.431 [main] INFO my.CompareTest - StringBuffer的执行时间:6
10:32:19.437 [main] INFO my.CompareTest - StringBuilder的执行时间:3
10:32:20.391 [main] INFO my.CompareTest - String的执行时间:954

结论:

三者在单线程顺序执行的情况下,三者执行速度 String < StringBuffer <(?存在疑问) StringBuilder

思考由于锁的优化,在性能上StringBuffer 与 StringBuilder对比,在单线程上运行其实是效率差不多的。

但是为什么执行结果会是StringBuffer慢,我尝试了先执行StringBuilder的测试代码

public static void main(String[] args) {

    //初始设置
    long startTime = 0L;
    long endTime = 0L;
    String text = "";
    StringBuffer buffer = new StringBuffer("");
    StringBuilder builder = new StringBuilder("");
    //开始对比
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 20000; i++) {
        builder.append(String.valueOf(i));
    }
    endTime = System.currentTimeMillis();
    log.info("StringBuilder的执行时间:{}", (endTime - startTime));
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 20000; i++) {
        buffer.append(String.valueOf(i));
    }
    endTime = System.currentTimeMillis();
    log.info("StringBuffer的执行时间:{}", (endTime - startTime));
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 20000; i++) {
        text += i;
    }
    endTime = System.currentTimeMillis();
    log.info("String的执行时间:{}", (endTime - startTime));
}

多次运行得到结果

10:42:44.781 [main] INFO my.CompareTest - StringBuilder的执行时间:3
10:42:44.787 [main] INFO my.CompareTest - StringBuffer的执行时间:2
10:42:45.775 [main] INFO my.CompareTest - String的执行时间:988

10:43:14.452 [main] INFO my.CompareTest - StringBuilder的执行时间:5
10:43:14.458 [main] INFO my.CompareTest - StringBuffer的执行时间:2
10:43:15.426 [main] INFO my.CompareTest - String的执行时间:967

10:43:25.328 [main] INFO my.CompareTest - StringBuilder的执行时间:4
10:43:25.335 [main] INFO my.CompareTest - StringBuffer的执行时间:2
10:43:26.295 [main] INFO my.CompareTest - String的执行时间:960

然后我又将String的循环添加放在最上面执行:

public static void main(String[] args) {

    //初始设置
    long startTime = 0L;
    long endTime = 0L;
    String text = "";
    StringBuffer buffer = new StringBuffer("");
    StringBuilder builder = new StringBuilder("");
    //开始对比
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 20000; i++) {
        text += i;
    }
    endTime = System.currentTimeMillis();
    log.info("String的执行时间:{}", (endTime - startTime));
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 20000; i++) {
        builder.append(String.valueOf(i));
    }
    endTime = System.currentTimeMillis();
    log.info("StringBuilder的执行时间:{}", (endTime - startTime));
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 20000; i++) {
        buffer.append(String.valueOf(i));
    }
    endTime = System.currentTimeMillis();
    log.info("StringBuffer的执行时间:{}", (endTime - startTime));
}

这次多次执行得到的结果为:

10:44:30.050 [main] INFO my.CompareTest - String的执行时间:970
10:44:30.055 [main] INFO my.CompareTest - StringBuilder的执行时间:2
10:44:30.057 [main] INFO my.CompareTest - StringBuffer的执行时间:2

10:45:26.505 [main] INFO my.CompareTest - String的执行时间:1026
10:45:26.515 [main] INFO my.CompareTest - StringBuilder的执行时间:2
10:45:26.518 [main] INFO my.CompareTest - StringBuffer的执行时间:3

10:45:38.223 [main] INFO my.CompareTest - String的执行时间:988
10:45:38.228 [main] INFO my.CompareTest - StringBuilder的执行时间:2
10:45:38.231 [main] INFO my.CompareTest - StringBuffer的执行时间:3

10:45:52.584 [main] INFO my.CompareTest - String的执行时间:1020
10:45:52.590 [main] INFO my.CompareTest - StringBuilder的执行时间:2
10:45:52.592 [main] INFO my.CompareTest - StringBuffer的执行时间:2

思考下,其实这样测试不太严谨,因为刚开始运行的时候,字符串常量池中是没有对象的。首次循环的时候会将需要添加的"1",“2”,“3”…字符串常量对象在字符串常量池中创建出来。而后续的循环操作是不需要花费这样的时间的。所以造成了最开始的结论看似是StringBuffer比StringBuilder慢。

然后我单独对StringBuffer和StringBuilder进行20000次添加(String就不测试了,因为有结论肯定比两者都慢):

1.先执行测试代码:

public static void builderTest(){
    //初始设置
    long startTime = 0L;
    long endTime = 0L;
    String text = "";
    StringBuffer buffer = new StringBuffer("");
    StringBuilder builder = new StringBuilder("");
    //开始对比
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 20000; i++) {
        builder.append(String.valueOf(i));
    }
    endTime = System.currentTimeMillis();
    log.info("StringBuilder的执行时间:{}", (endTime - startTime));
}

执行结果:

StringBuilder的执行时间:3

StringBuilder的执行时间:4

StringBuilder的执行时间:5

2.执行

public static void bufferTest(){
    //初始设置
    long startTime = 0L;
    long endTime = 0L;
    StringBuffer buffer = new StringBuffer("");
    //开始对比
    startTime = System.currentTimeMillis();
    for (int i = 0; i < 20000; i++) {
        buffer.append(String.valueOf(i));
    }
    endTime = System.currentTimeMillis();
    log.info("StringBuffer的执行时间:{}", (endTime - startTime));
}

执行结果:

10:49:24.713 [main] INFO my.CompareTest - StringBuffer的执行时间:3

10:51:33.559 [main] INFO my.CompareTest - StringBuffer的执行时间:4

10:51:33.559 [main] INFO my.CompareTest - StringBuffer的执行时间:5

从结果上看在jdk1.8,单线程的情况下,StringBuffer和StringBuilder循环20000次并没有太大区别。

因为在jdk1.6及之后对synchronized进行了优化,在没有线程竞争的情况下,只会上偏向锁,甚至还会有可能被jvm的逃逸分析分析成未逃逸,优化成无锁状态,所以二者并没有差别。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值