Java字符串鏈接效率

字符串操做是編寫程序中最多見的行爲,本文對String、StringBuilder、StringBuffer三個類在字符串處理方面的效率進行分析。
     Java中最多見也是應用最普遍的類就是String類。
    
    
    
    
    
  1. String:Strings are constant; their values cannot be changed after they are created. 
     這是JDK對String的解釋,意思是:String是常量,一旦建立後它的值不能被修改。
     先看String對象是如何建立的:
    
    
    
    
    
  1. String str1 = 「abc」; 
  2. String str2 = new String(「abc」); 
     這是咱們常見的兩種形式。
    第一種方式建立的字符串會放在棧裏,更確切的是常量池中,常量池就是用來保存在編譯階段肯定好了大小的數據,通常咱們定義的int等基本數據類型就保存在這裏。其具體的一個流程就是,編譯器首先檢查常量池,看看有沒有一個「abc」,若是沒有則建立。若是有的話,則則直接把str1指向那個位置。
    第二種建立字符串的方法是經過new關鍵字,仍是java的內存分配,java會將new的對象放在堆中,這一部分對象是在運行時建立的對象。因此咱們每一次new的時候,都會建立不一樣的對象,即使是堆中已經有了一個如出一轍的。
     下面的程序將驗證上面的說法。
 
    
    
    
    
  1. String str1 = "abc"
  2.  String str2 = new String("abc"); 
  3.   
  4.  String str3 = "abc"
  5.  String str4 = new String("abc"); 
  6.   
  7.  System.out.println(str1==str2);//false 
  8.           
  9.  System.out.println(str1 == str3);//true 
  10.  System.out.println(str2 == str4);//false 
  11.  // When the intern method is invoked, if the pool already contains a 
  12.  // string equal to this String object as determined by the 
  13.  // equals(Object) method, then the string from the pool is returned. 
  14.  // Otherwise, this String object is added to the pool and a reference to 
  15.  // this String object is returned. 
  16.  str2 = str2.intern(); 
  17.  System.out.println(str1==str2);//true 
  18.  
  19. //output:
  20.  //false 
  21.  //true 
  22.  //false 
  23.  //true 
 
     以上程序中用兩種方式建立的4個對象,」==」比較的是地址,從結果能夠看到str1和str3相同,指向同一個對象。而str2和str4比較返回結果是false,說明str2和str4指向的不是同一個對象。
     (上面用到了一個比較少見的方法:intern。在str2調用了intern方法後對str1和str2進行比較返回true,能夠從代碼註釋中看明白,intern方法返回常量池中內容和該對象相同的對象,若是常量池中不存在,則將該對象加入到常量池中。)
     String對象是不變的,那爲何能夠進行str+=」abc」這樣的操做?其實相似這樣的操做是新生成了一個String對象,包含str和abc鏈接後的字符串。
 
    
    
    
    
  1. package test; 
  2.  public class StringTest { 
  3.      public static void main(String[] args) { 
  4.          String str1 = "abc"
  5.          str1 += "123"
  6.      } 
  7.  } 
 
    
 
 從編譯以後的class能夠看出編譯器自動引入了StringBuilder類,經過它的初始化方法建立了StringBuilder對象,經過append方法添加了內容,調用toString返回鏈接後的對象。以上內容證實了String對象是不可變的,鏈接操做實際是返回了新的對象。若是是循環屢次進行鏈接,將不斷的建立StringBuilder對象,append新內容,toString成String對象。這就帶來了String類處理字符串更改操做的效率問題。
 
    
    
    
    
  1. public class StringTest { 
  2.      public static void main(String[] args) { 
  3.          long start, end; 
  4.   
  5.          StringBuilder strBuilder = new StringBuilder(" "); 
  6.          start = System.currentTimeMillis(); 
  7.          for (int i = 0; i < 100000; i++) { 
  8.              strBuilder.append(" "); 
  9.          } 
  10.          end = System.currentTimeMillis(); 
  11.          System.out.println("StringBuilder append: " + (end - start) + "ms"); 
  12.   
  13.          String str = " "
  14.          start = System.currentTimeMillis(); 
  15.          for (int i = 0; i < 100000; i++) { 
  16.              str += " "
  17.          } 
  18.          end = System.currentTimeMillis(); 
  19.          System.out.println("String +: " + (end - start) + "ms"); 
  20.      } 
  21.  } 
 
 
   能夠看到String和StringBuilder在效率方便的差距。
    
    
    
    
    
  1. StringBuffer:A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified. 
  2. StringBuilder:A mutable sequence of characters. This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. 
    StringBuffer是可變的、線程安全的字符串。StringBuilder就是StringBuffer的非線程同步的版本,兩者的方法差很少,只是一個線程安全(適用於多線程)一個沒有線程安全(適用於單線程)。
相關文章
相關標籤/搜索