String和StringBuffer性能比较

先来看看两个简单字符串相连的情况,上代码  

 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 +号连接是相当耗费资源和时间的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值