您的位置:首页 > Web前端

String和StringBuffer性能比较

2013-03-01 20:10 393 查看
先来看看两个简单字符串相连的情况,上代码

1 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方法进行的。

所以在少量简单字符串与变量的连接时,两者效率是基本上一样的

下面我们来看最后一种情况。 大量的字符串与变量的连接 上代码

1 public class Test2 {
2 public static String testJoinString(){

3 String str = "a" ;

4 for(int i=0;i<100;i++){

5 str += "a" + i ;

6 }

7 return str ;

8 }

9

10 public static String testJoinStringBuffer(){

11 StringBuffer sb = new StringBuffer();

12 for(int i =0;i<100;i++){

13 sb.append("a") ;

14 sb.append(i) ;

15 }

16 return sb.toString() ;

17 }

18 }

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 的+号连接是相当耗费资源和时间的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: