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));
}
-
测试的结果:
StringBuilder cost: 5 StringBuffer cost: 9 String cost: 14029
在循环中,String 拼接字符串的速度远低于 StringBuilder 和 StringBuffer
利用 javap 查看字节码文件,寻找其中的差异
-
命令行执行
javap -c StringTest.class
结果可以看出,String 拼接的时候也是通过 StringBuilder 的 append 方法进行拼接的
产生差异的原因是,在每次循环中,String 拼接的时候都 new 了一个 StringBuilder
-
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); }
-
字节码
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 方法
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。