ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

“+“、String.concat、StringBuild.append 效率竞速

2021-07-13 09:34:49  阅读:212  来源: 互联网

标签:lang java String 竞速 StringBuilder append str concat


代码测试

public static void main(String[] args) throws InterruptedException {
        int testLength = 10000 ;

        long l ;
        String str ;
        //+
        l = System.currentTimeMillis();
        str = "";
        for (int i = 0; i < testLength; i++) {
            str = str + String.valueOf(i);
        }
        System.out.println("+ :" + (System.currentTimeMillis() - l));

        //concat 
        l = System.currentTimeMillis();
        str = "";
        for (int i = 0; i < testLength; i++) {
            str.concat(String.valueOf(i));
        }
        System.out.println("concat :" + (System.currentTimeMillis() - l));

        //StringBuilder
        l = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < testLength; i++) {
            sb.append(String.valueOf(i));
        }
        System.out.println("StringBuilder :" + (System.currentTimeMillis() - l));

    }

输出结果

+ :704
concat :4
StringBuilder :2

多次试验,由上面可以大致得出以下结论,StringBuilder.append > String.concat > "+"

为什么 "+" 性能这么低?

为了探讨"+"的本质,我们打印 "+"的字节码,采用 javap -c xxx.class命令。

12: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
15: lstore_2
16: ldc           #3                  // String
18: astore        4
20: iconst_0                          iconst_0 是数字 0
21: istore        5
23: iload         5
25: iload_1                           表示局部变量1,这里就是源码里的 i 了
26: if_icmpge     60
29: new           #4                  // class java/lang/StringBuilder
32: dup
33: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
36: aload         4
38: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: iload         5
43: invokestatic  #7                  // Method java/lang/String.valueOf:(I)Ljava/lang/String;
46: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
49: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
52: astore        4
54: iinc          5, 1
57: goto          23
60: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
63: new           #4                  // class java/lang/StringBuilder
66: dup
67: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
70: ldc           #10                 // String + :
72: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
75: invokestatic  #2                  // Method java/lang/System.currentTimeMillis:()J
78: lload_2
79: lsub
80: invokevirtual #11                 // Method java/lang/StringBuilder.append:(J)Ljava/lang/StringBuilder;
83: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
86: invokevirtual #12                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
89: invokestatic  #2                  // Method

这里我们基本可以确定一件事情,"+"转换成了StringBuild对象,这里但是为什么性能和StringBuild差的这么远呢?

我们分析字节码指令可知,当我们使用“+”时,循环包裹着StringBuild.

​
//实例
    for (int i = 0; i < testLength; i++) {
        str = str + String.valueOf(i);
     }
//等价于
    for (int i = 0; i < testLength; i++) {
        StringBuilder sb = new StringBuilder();
        sb.append(str);
        sb.append(String.valueOf(i));
        str = sb.toString();
    }

​

**为了验证结论,我们再次分析字节码,发现二者字节码几乎一模一样。

由此,我们得到一个重要的结论
当不做循环累加时,我们使用"+"的性能和使用StringBuild.append 性能几乎一致。

StringBuild.append和String.concat性能比较

当们做对比试验时,发现StringBuild和concat的性能太相近了,很难做出试验对比,于是乎我们对比源码分析。

String.concat:
先扩容,然后在调用getChars,最后new一个类返回

    public String concat(String str) {
        int otherLen = str.length();
        if (otherLen == 0) {
            return this;
        }
        int len = value.length;
        char buf[] = Arrays.copyOf(value, len + otherLen);
        str.getChars(buf, len);
        return new String(buf, true);
    }

StringBuild.append:
先扩容(与当前len比较),然后在调用getChars,最后new一个类返回

    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
    private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

我们经过对比源码后可以发现StringBuild.append略快一点,因为 不用new 一个 String类返回。

标签:lang,java,String,竞速,StringBuilder,append,str,concat
来源: https://blog.csdn.net/qq_35471409/article/details/118692017

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有