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

    故而在大量的连接的情况。StringBuffer 的效率明显要高于String+连接    


      

  • 相关阅读:
    Java环境搭建
    Java语言的分支
    Java语言概述
    计算机语言
    人机交互
    计算机分类
    计算机的应用领域
    计算机的发展史
    Java8的一些新特性
    python国内三方库下载镜像
  • 原文地址:https://www.cnblogs.com/jivi/p/2881266.html
Copyright © 2020-2023  润新知