String和StringBuffer效率比较
2016-08-15 22:43
357 查看
先来看看两个简单字符串相连的情况,上代码
编译完成后,我们CMD里
javap -verbose Test >> Test.txt 将字节码反编译成JAVA中间代码。直接看主体部分。
--------------------------------------------
public static java.lang.String testJoinString();
Code:
Stack=1, Locals=1, Args_size=0
0: ldc #16; //String aa
2: astore_0
3: aload_0
4: areturn
public static java.lang.String testJoinStringBuffer();
Code:
Stack=2, Locals=1, Args_size=0
0: new #21; //class java/lang/StringBuffer
3: dup
4: invokespecial #23; //Method java/lang/StringBuffer."<init>":()V
7: astore_0
8: aload_0
9: ldc #24; //String a
11: invokevirtual #26; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
14: pop
15: aload_0
16: ldc #24; //String a
18: invokevirtual #26; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
21: pop
22: aload_0
23: invokevirtual #30; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
26: areturn
--------------------------------------------
看红色的部分
String连接的情况下:
0: ldc #16; //String aa ,
可以看到在编译的时候,已经直接进行了表达式合并优化,所以直接就加载了 aa
StringBuffer的情况下:
9: ldc #24; //String a
16: ldc #24; //String a
加载了二次
从上面我们看到,在少量的简单字符串与字符串的连接,不涉及变量的情况下。String的+号连接在编译时已经进行了优化,所以效率是要比StringBuffer高的。
下面我们再来看看 简单的字符串和变量相连的情况,上代码
同样 CMD里 javap -verbose Test1 >> Test1.txt
看主体部分
--------------------------------------------
public static java.lang.String testJoinString();
Code:
Stack=3, Locals=2, Args_size=0
0: ldc #16; //String a
2: astore_0
3: new #18; //class java/lang/StringBuilder
6: dup
7: ldc #16; //String a
9: invokespecial #20; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
12: aload_0
13: invokevirtual #23; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: invokevirtual #27; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
19: astore_1
20: aload_1
21: areturn
--------------------------------------------
StringBuffer部分代码没有变更为节省篇幅,这里就不现列出来,可以拉上去看一看
再看红色部分
String 的+号连接
0: ldc #16; //String a
7: ldc #16; //String a
13: invokevirtual #23;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
可以看出其实String的+号连接,仍然是调用了StringBuffer.append方法进行的。
所以在少量简单字符串与变量的连接时,两者效率是基本上一样的
下面我们来看最后一种情况。 大量的字符串与变量的连接 上代码
Javap -verbose Test2 >> Test2.txt
主体部分
--------------------------------------------
public static java.lang.String testJoinString();
Code:
Stack=3, Locals=2, Args_size=0
0: ldc #16; //String a
2: astore_0
3: iconst_0
4: istore_1
5: goto 35
8: new #18; //class java/lang/StringBuilder
11: dup
12: aload_0
13: invokestatic #20;
//Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
16: invokespecial #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
19: ldc #16; //String a
21: invokevirtual #29;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: iload_1
25: invokevirtual #33;
//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
28: invokevirtual #36; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore_0
32: iinc 1, 1
35: iload_1
36: bipush 100
38: if_icmplt 8
41: aload_0
42: areturn
public static java.lang.String testJoinStringBuffer();
Code:
Stack=2, Locals=2, Args_size=0
0: new #45; //class java/lang/StringBuffer
3: dup
4: invokespecial #47; //Method java/lang/StringBuffer."<init>":()V
7: astore_0
8: iconst_0
9: istore_1
10: goto 29
13: aload_0
14: ldc #16; //String a
16: invokevirtual #48;
//Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
19: pop
20: aload_0
21: iload_1
22: invokevirtual #51; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
25: pop
26: iinc 1, 1
29: iload_1
30: bipush 100
32: if_icmplt 13
35: aload_0
36: invokevirtual #54; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
39: areturn
------------------------------------------
看上面的红色部分 (主体部分)
testJoinString
5: goto 35
8: new #18; //class java/lang/StringBuilder
19: ldc #16; //String a
21: invokevirtual #29;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
25: invokevirtual #33;
//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
28: invokevirtual #36; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
36: bipush 100
38: if_icmplt 8
testJoinStringBuffer
0: new #45; //class java/lang/StringBuffer
13: aload_0
14: ldc #16; //String a
16: invokevirtual #48;
// Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
22: invokevirtual #51; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
30: bipush 100
32: if_icmplt 13
从上面可以看出来。String的+号连接,在循环体内部(8~28),每次都要 new 一个StringBuffer 出来,而 StringBuffer.append 方法,只是在循环体外,new 一个StringBuffer出来 。
这样如果循环很大的话,String 的+号连接是相当耗费资源和时间的。
故而在大量的连接的情况。StringBuffer 的效率明显要高于String的+连接
=================================================
参见:
http://www.cnblogs.com/jivi/archive/2013/02/28/2881266.html
public class Test { 2 public static String testJoinString() { 3 String str = "a" + "a"; 4 return str; 5 } 6 7 public static String testJoinStringBuffer() { 8 StringBuffer sb = new StringBuffer(); 9 sb.append("a"); 10 sb.append("a"); 11 return sb.toString(); 12 } 13 }
编译完成后,我们CMD里
javap -verbose Test >> Test.txt 将字节码反编译成JAVA中间代码。直接看主体部分。
--------------------------------------------
public static java.lang.String testJoinString();
Code:
Stack=1, Locals=1, Args_size=0
0: ldc #16; //String aa
2: astore_0
3: aload_0
4: areturn
public static java.lang.String testJoinStringBuffer();
Code:
Stack=2, Locals=1, Args_size=0
0: new #21; //class java/lang/StringBuffer
3: dup
4: invokespecial #23; //Method java/lang/StringBuffer."<init>":()V
7: astore_0
8: aload_0
9: ldc #24; //String a
11: invokevirtual #26; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
14: pop
15: aload_0
16: ldc #24; //String a
18: invokevirtual #26; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
21: pop
22: aload_0
23: invokevirtual #30; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
26: areturn
--------------------------------------------
看红色的部分
String连接的情况下:
0: ldc #16; //String aa ,
可以看到在编译的时候,已经直接进行了表达式合并优化,所以直接就加载了 aa
StringBuffer的情况下:
9: ldc #24; //String a
16: ldc #24; //String a
加载了二次
从上面我们看到,在少量的简单字符串与字符串的连接,不涉及变量的情况下。String的+号连接在编译时已经进行了优化,所以效率是要比StringBuffer高的。
下面我们再来看看 简单的字符串和变量相连的情况,上代码
1 public class Test1 { 2 public static String testJoinString(){ 3 String str1 = "a" ; 4 String str2 = "a" + str1 ; 5 return str2 ; 6 } 7 public static String testJoinStringBuffer(){ 8 StringBuffer sb = new StringBuffer(); 9 sb.append("a") ; 10 sb.append("a") ; 11 return sb.toString() ; 12 } 13 }
同样 CMD里 javap -verbose Test1 >> Test1.txt
看主体部分
--------------------------------------------
public static java.lang.String testJoinString();
Code:
Stack=3, Locals=2, Args_size=0
0: ldc #16; //String a
2: astore_0
3: new #18; //class java/lang/StringBuilder
6: dup
7: ldc #16; //String a
9: invokespecial #20; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
12: aload_0
13: invokevirtual #23; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: invokevirtual #27; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
19: astore_1
20: aload_1
21: areturn
--------------------------------------------
StringBuffer部分代码没有变更为节省篇幅,这里就不现列出来,可以拉上去看一看
再看红色部分
String 的+号连接
0: ldc #16; //String a
7: ldc #16; //String a
13: invokevirtual #23;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
可以看出其实String的+号连接,仍然是调用了StringBuffer.append方法进行的。
所以在少量简单字符串与变量的连接时,两者效率是基本上一样的
下面我们来看最后一种情况。 大量的字符串与变量的连接 上代码
public class Test2 { public static String testJoinString(){ String str = "a" ; for(int i=0;i<100;i++){ str += "a" + i ; } return str ; } public static String testJoinStringBuffer(){ StringBuffer sb = new StringBuffer(); for(int i =0;i<100;i++){ sb.append("a") ; sb.append(i) ; } return sb.toString() ; } }
Javap -verbose Test2 >> Test2.txt
主体部分
--------------------------------------------
public static java.lang.String testJoinString();
Code:
Stack=3, Locals=2, Args_size=0
0: ldc #16; //String a
2: astore_0
3: iconst_0
4: istore_1
5: goto 35
8: new #18; //class java/lang/StringBuilder
11: dup
12: aload_0
13: invokestatic #20;
//Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
16: invokespecial #26; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
19: ldc #16; //String a
21: invokevirtual #29;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: iload_1
25: invokevirtual #33;
//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
28: invokevirtual #36; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore_0
32: iinc 1, 1
35: iload_1
36: bipush 100
38: if_icmplt 8
41: aload_0
42: areturn
public static java.lang.String testJoinStringBuffer();
Code:
Stack=2, Locals=2, Args_size=0
0: new #45; //class java/lang/StringBuffer
3: dup
4: invokespecial #47; //Method java/lang/StringBuffer."<init>":()V
7: astore_0
8: iconst_0
9: istore_1
10: goto 29
13: aload_0
14: ldc #16; //String a
16: invokevirtual #48;
//Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
19: pop
20: aload_0
21: iload_1
22: invokevirtual #51; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
25: pop
26: iinc 1, 1
29: iload_1
30: bipush 100
32: if_icmplt 13
35: aload_0
36: invokevirtual #54; //Method java/lang/StringBuffer.toString:()Ljava/lang/String;
39: areturn
------------------------------------------
看上面的红色部分 (主体部分)
testJoinString
5: goto 35
8: new #18; //class java/lang/StringBuilder
19: ldc #16; //String a
21: invokevirtual #29;
//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
25: invokevirtual #33;
//Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
28: invokevirtual #36; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
36: bipush 100
38: if_icmplt 8
testJoinStringBuffer
0: new #45; //class java/lang/StringBuffer
13: aload_0
14: ldc #16; //String a
16: invokevirtual #48;
// Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer;
22: invokevirtual #51; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer;
30: bipush 100
32: if_icmplt 13
从上面可以看出来。String的+号连接,在循环体内部(8~28),每次都要 new 一个StringBuffer 出来,而 StringBuffer.append 方法,只是在循环体外,new 一个StringBuffer出来 。
这样如果循环很大的话,String 的+号连接是相当耗费资源和时间的。
故而在大量的连接的情况。StringBuffer 的效率明显要高于String的+连接
=================================================
参见:
http://www.cnblogs.com/jivi/archive/2013/02/28/2881266.html
相关文章推荐
- java中String、StringBuilder和StringBuffer效率的比较
- java String常用操作以及比较用String与StringBuffer追加字符的执行效率【修订2】
- 七种java字符串反转比较得出String与StringBuffer的效率
- [Java]String和StringBuffer连接字串的效率比较
- String与StringBuffer效率的比较
- String,StringBuffer,StringBuilder效率与内存占用比较
- String与StringBuffer效率的比较
- String、StringBuffer、StringBuilder的区别与效率比较
- Java学习札记14:一个比较String、StringBuffer和StringBuilder之间效率差别的简单例子
- String 与 StringBuffer效率比较
- String 与 StringBuffer 的效率比较
- String和StringBuffer效率比较
- StringBuffer和String效率比较
- String, StringBuffer, StringBuilder拼接字符串的执行效率比较
- 再传一点今天的开发日志上来,主要是String和StringBuffer效率问题比较
- String,StringBuffer,StringBuilder效率优先关系说明
- String, StringBuffer, StringBuilder 三个类比较
- String & StringBuffer的比较
- String 与StringBuffer比较
- 38.黑马程序员-String、StringBuffer、StringBuilder比较