Java字符串連接效率


     字符串操作是編寫程序中最常見的行為,本文對String、StringBuilder、StringBuffer三個類在字符串處理方面的效率進行分析。

     Java中最常見也是應用最廣泛的類就是String類。

     String:Strings are constant; their values cannot be changed after they are created.

     這是JDK對String的解釋,意思是:String是常量,一旦創建后它的值不能被修改。

     先看String對象是如何創建的:

     String str1 = “abc”;

     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 false
20 true
21 false
22 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 
3 public class StringTest {
4     public static void main(String[] args) {
5         String str1 = "abc";
6         str1 += "123";
7     }
8 }

     從編譯之后的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在效率方面的差距。

     StringBuffer:A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified.

     StringBuilder:A mutable sequence of characters. This class provides an API compatible with StringBuffer, but with no guarantee of synchronization.

     StringBuffer是可變的、線程安全的字符串。StringBuilder就是StringBuffer的非線程同步的版本,二者的方法差不多,只是一個線程安全(適用於多線程)一個沒有線程安全(適用於單線程)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM