String、StringBuilder、StringBuffer 拼接測試

String、StringBuilder、StringBuffer

測試拼接速度

@Test
public void testString() {
    long before = System.currentTimeMillis();
    String s = "";
    for (int i = 0; i < 100000; i++) {
        s += "a";
    }
    long after = System.currentTimeMillis();
    System.out.println("String cost: " + (after - before));
}

@Test
public void testStringBuilder() {
    long before = System.currentTimeMillis();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < 100000; i++) {
        sb.append("a");
    }
    long after = System.currentTimeMillis();
    System.out.println("StringBuilder cost: " + (after - before));
}

@Test
public void testStringBuffer() {
    long before = System.currentTimeMillis();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < 100000; i++) {
        sb.append("a");
    }
    long after = System.currentTimeMillis();
    System.out.println("StringBuffer cost: " + (after - before));
}
  • 測試的結果:java

    StringBuilder cost: 5
        StringBuffer cost: 9
        String cost: 14029
  • 在循環中,String 拼接字符串的速度遠低於 StringBuilder 和 StringBuffer安全

利用 javap 查看字節碼文件,尋找其中的差別

  • 命令行執行app

    javap -c StringTest.class
  • 結果能夠看出,String 拼接的時候也是經過 StringBuilder 的 append 方法進行拼接的測試

  • 產生差別的緣由是,在每次循環中,String 拼接的時候都 new 了一個 StringBuilderui

  • StringBuffer 是線程安全的,只比 StringBuilder 稍慢了一點命令行

    public void testString();
    Code:
    0: ldc           #2                  // String
    2: astore_1
    3: iconst_0
    4: istore_2
    5: iload_2
    6: ldc           #11                 // int 100000
    8: if_icmpge     37
    11: new           #4                  // class java/lang/StringBuilder
    14: dup
    15: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
    18: aload_1
    19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    22: ldc           #9                  // String a
    24: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    27: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    30: astore_1
    31: iinc          2, 1
    34: goto          5
    37: return
    
    public void testStringBuilder();
    Code:
    0: new           #4                  // class java/lang/StringBuilder
    3: dup
    4: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
    7: astore_1
    8: iconst_0
    9: istore_2
    10: iload_2
    11: ldc           #11                 // int 100000
    13: if_icmpge     29
    16: aload_1
    17: ldc           #9                  // String a
    19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    22: pop
    23: iinc          2, 1
    26: goto          10
    29: return
    
    public void testStringBuffer();
    Code:
    0: new           #12                 // class java/lang/StringBuffer
    3: dup
    4: invokespecial #13                 // Method java/lang/StringBuffer."<init>":()V
    7: astore_1
    8: iconst_0
    9: istore_2
    10: iload_2
    11: ldc           #11                 // int 100000
    13: if_icmpge     29
    16: aload_1
    17: ldc           #9                  // String a
    19: invokevirtual #14                 // Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
    22: pop
    23: iinc          2, 1
    26: goto          10
    29: return

若不是循環,String 和 StringBuilder 拼接的速度是差很少的

  • java 測試代碼線程

    @Test
    public void string() {
        String s = "";
        String ss = "cc";
        s += "a" + "b" + ss;
    }
        
    @Test
    public void stringBuilder() {
        StringBuilder sb = new StringBuilder();
        String ss = "cc";
        sb.append("a").append("b").append(ss);
    }
  • 字節碼code

    public void string();
    Code:
    0: ldc           #2                  // String
    2: astore_1
    3: ldc           #3                  // String cc
    5: astore_2
    6: new           #4                  // class java/lang/StringBuilder
    9: dup
    10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
    13: aload_1
    14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    17: ldc           #7                  // String ab
    19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    22: aload_2
    23: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    26: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    29: astore_1
    30: return
    
    public void stringBuilder();
    Code:
    0: new           #4                  // class java/lang/StringBuilder
    3: dup
    4: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
    7: astore_1
    8: ldc           #3                  // String cc
    10: astore_2
    11: aload_1
    12: ldc           #9                  // String a
    14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    17: ldc           #10                 // String b
    19: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    22: aload_2
    23: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    26: pop
    27: return
  • 緣由是一樣只 new 了一個 StringBuilder,使用的也是它的 append 方法ci

相關文章
相關標籤/搜索