@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安全
命令行執行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
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