String、StringBuffer、StringBuilder 性能测试

这几个时常用于比较,我们通过实验来分析其性能,然后试图去寻找背后的原因。

实验总的代码:

public class Test {
    final static int NUM = 100000;

    public static void testString(String str){
        long start = System.currentTimeMillis();
        for(int i=0; i<NUM; i++){
            str += "append-";
        }
        long end = System.currentTimeMillis();
        System.out.println(str.getClass().getName() + " 共占用了 :  "+  (end-start) + " 毫秒");
    }


    public static void testString(StringBuffer str){
        long start = System.currentTimeMillis();
        for(int i=0; i<NUM; i++){
            str.append("append-") ;
        }
        long end = System.currentTimeMillis();
        System.out.println(str.getClass().getName() + " 共占用了 :  "+  (end-start) + " 毫秒");
    }


    public static void testString(StringBuilder str){
        long start = System.currentTimeMillis();
        for(int i=0; i<NUM; i++){
            str.append("append-");
        }
        long end = System.currentTimeMillis();
        System.out.println(str.getClass().getName() + " 共占用了 :  "+  (end-start) + " 毫秒");
    }


  //字符串對象引用相加
    public static void testStringAppend(){
        String str = "abc";
        long start = System.currentTimeMillis();
        for(int i=0; i<NUM; i++){
            String newStr = str+ str+ str;
        }
        long end = System.currentTimeMillis();
        System.out.println("字符串对象引用相加类型使用的时间为: " + " 共占用了 :  "+  (end-start) + " 毫秒");
    }



    //字符串直接相加
    public static void testStringAdd(){
        long start = System.currentTimeMillis();
        for(int i=0; i<NUM; i++){
            String newStr = "abc"+ "abc" + "abc";
        }
        long end = System.currentTimeMillis();
        System.out.println("字符串相加:  " + " 共占用了 :  "+  (end-start) + " 毫秒");
    }


    public static void main(String[] args) {
         String s= "asdf";
         StringBuffer sbf = new StringBuffer("asdf");
         StringBuilder sbd = new StringBuilder("asdf");

         Test.testString(s);          (1)
         Test.testString(sbf);         (2)
         Test.testString(sbd);          (3)

         Test.testStringAdd();           (4)
         Test.testStringAppend();          (5)
    }
}


结果:
java.lang.String 共占用了 :         26996 毫秒
java.lang.StringBuffer 共占用了 :   6 毫秒
java.lang.StringBuilder 共占用了 :  4 毫秒
字符串相加:   共占用了 :             1 毫秒
字符串对象引用相加类型使用的时间为:  共占用了 :  13 毫秒

具体分析:

1、执行(1)所花时间最长,是其他的上万倍,可见其性能不大好哇。
原因分析:我们可以通过一次小实验来分析其原因。

public class TestSmaller {
    public static void main(String[] args) {
        String str1 = "append-";
        String str2 = "asdf-";
        String str3 = "append-"+"asdf-" ;
        String str4 = str1 + str2;

        System.out.println(str4.equals(str3) +"  其內容是:    "+ str3);
        System.out.println(str3 == str4);
        System.out.println(str3.hashCode());
        System.out.println(str4.hashCode());

    }
}

输出结果:
true  其內容是:    append-asdf-
false
210131462
210131462

从上面可知,str3 与 str4 其实是两个不同的对象(String 重写了hashcode() 和 equals() 方法,所以 输出的hashcode必然是一样的)。所以,也就是说,每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象。所以,当不断循环时,之前的 string对象将不在被引用,会触发JVM的GC,所以速度慢。

2、执行(2)的时候,从代码 str.append(“append-“); 也可以看出 ,是在原来对象的做值的修改,而且是县城安全的:

public synchronized StringBuffer append(String str) {
        super.append(str);
        return this;
    }

而super.append(str);  指的是基类中

public AbstractStringBuilder append(String str) {
        if (str == null) str = "null";
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }

3、执行(3)中的时候,与(2)中几乎无差异,只是它不是线程安全的,所以稍微快点:

    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }

4、执行(4)中所花的时间几乎就是for() 所花费的时间,应为 newStr只要执行一次 就可以了。

5、执行(5)时,每次都要去str所指向的地址找到相应的值,然后做拼接,所以花费的时间是(4)的数倍。

结论:
1、性能方面:
StringBuilder >(略大于) StringBuffer >>(远大于) String;
2、StringBuffer 是线程安全的、可变;
3、经常改变内容的字符串最好不用 String 类型。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值