My Calendar

2012年5月5日 星期六

String,StringBuilder和StringBuffer的區別

      在日常開發中串接字串是常有的工作,Java有三種方式處理字串串接分別是String, StringBuilderStringBuffer(JDK1.5 才提供) 這三種都可以達到我們想要的效果,但各自在使用上還是有些區別。

具體看以下的例子講解:
String str = "" ;
for(int i=0 ; i<10000 ; i++)
    str+="java";

相信大家都知道String這個類別是屬於Immutable Object,不知道的可以到Java String和String Pool查看。以這段code來說用迴圈進行大量的串接字串的工作,在效能上會有隱憂。所以Java提供了其他的方法提高效能。

我們為這三個方式做一個小測試。

public class Test {
 public static void main(String args[])
 {
  testString();
  testStringBuffer();
  testStringBuilder();
 }
 
 public static void testString()
 {
  String str = "" ;
  long begin = System.currentTimeMillis();  
  for(int i=0 ; i<10000 ; i++)
   str+="java";
                long end = System.currentTimeMillis();       
                System.out.println("String Spend Time:"+(end-begin)+"ms");
 }
 
 public static void testStringBuffer()
 {
  StringBuffer sbuf = new StringBuffer();
  long begin = System.currentTimeMillis();
  for(int i=0 ; i<10000 ; i++)
   sbuf.append(i);
  long end = System.currentTimeMillis();       
  System.out.println("String Buffer Time:"+(end-begin)+"ms");
 }
 
 public static void testStringBuilder()
 {
  StringBuilder sb = new StringBuilder();
  long begin = System.currentTimeMillis();
  for(int i=0 ; i<10000 ; i++)
      sb.append("java");
         long end = System.currentTimeMillis();  
         System.out.println("String Builder Spend Time:"+(end-begin)+"ms");
 }
 
}

執行結果:






從上面的結果可以看到同樣的工作StringBuilderStringBuffer的處理時間是差不多,但String的處理時間相對於其他兩種方式慢了很多。

在一般情況執行效率StringBuilder>StringBuffer>String,不一定所有情況都是這樣。

String: 適合在少量的字符串操作的情況。
StringBuilder:適合在單線程下進行大量操作的情況
StringBuffer:適合在多線程進行大量操作的情況

在compile的時候可以確定字串的常量,那沒必要使用StringBuilderStringBuffer,直接使用String常量"+"進行連接效率最好。



2012年5月2日 星期三

Java String和String Pool

     在開發Java應用程式當中String是我們常用的一個物件,要理解String的運作方式,首先要知道String是一個Immutable Object

宣告
宣告String有兩種方式 :
String str1 = "abc";
String str2 = new String("abc");
雖然這兩種方式都可以宣告String的物件,但JVM對於這兩種的處理方式是不一樣的。第一種首先會在String Pool中尋找是否存在,如果有就從String Pool回傳該String物件,反之將該常量新增到String Pool中。第二種則會在Heap Memory新增一個物件,而不是String Pool中。

String Pool
String Pool是Java Heap Memory中儲存String的一個區域。當使用常量(literal)方式宣告String物件JVM會從String Pool檢查是否有相同的字串,如果有將會從String Pool回傳該實例,而不會重分配新的記憶體,從而達到節省記憶體的目的。

例子:
String str1 = "abc";
String str2 = "abc";


















使用new關鍵字宣告的方式就會在Heap Memory新增一個字串,而不管該字串是否在String Pool中。
String str3 = new String("abc");
String str4 = new String("abc");

















我們看以下的code就能更加清楚。
public class Test {
 public static void main(String args[])
 {
  String str1 = "abc";
  String str2 = "abc";
  String str3 = new String("abc");
  String str4 = new String("abc");
  
  System.out.println(str1==str2);
  System.out.println(str1==str3);
  System.out.println(str3==str4);
  System.out.println(str1==str3.intern()); 
 }
}

執行的結果是
true
false
false
true

==只能判定兩個instance是否指向同一個記憶體位址(M.A),而不是M.A裡面的內容。從結果可以看出 str1==str2 是true原因是雙方都是指向在String pool裡面同一個M.A,反之str1==str3會是false

雖然str3的內容和str1一樣,但因為宣告方式的不同造成str3不會在String pool裡面尋找,而是直接在Heap memory重新分配新的M.A給str3。str3==str4是false也是M.A的不同。在String有一個方法可以先從String Pool裡面尋找該內容那就是intern()。str1==str3.intern()是true是可以預料的,str3調用intern()方法造成str3指向的M.A會和str1一樣。