String StringBuffer StringBuilder

StringBuilder 是 JDK5.0 中新增加的一個類,它跟 StringBuffer 的區別看下面的介紹
    Java.lang.StringBuffer 線程安全的可變字符序列。類似於 String 的字符串緩衝區,但不能修改。可將字符串緩衝區安全地用於多個線程。可以在必要時對這些方法進行同步,因此任意特定實例上的所有操作就好像是以串行順序發生的,該順序與所涉及的每個線程進行的方法調用順序一致。
   每個字符串緩衝區都有一定的容量。只要字符串緩衝區所包含的字符序列的長度沒有超出此容量,就無需分配新的內部緩衝區數組。如果內部緩衝區溢出,則此容量自動增大。從 JDK 5.0 開始,爲該類增添了一個單個線程使用的等價類,即 StringBuilder 。與該類相比,通常應該優先使用 StringBuilder 類,因爲它支持所有相同的操作,但由於它不執行同步,所以速度更快。 但是如果將 StringBuilder 的實例用於多個線程是不安全的。需要這樣的同步,則建議使用 StringBuffer 。
StringBuilder > StringBuffer > String
1.  爲了獲得更好的性能,在構造 StirngBuffer 或 StirngBuilder 時應儘可能指定它的容量。當然,如果你操作的字符串長度不超過 16 個字符就不用了。

2.  相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風險。而在現實的模塊化編程中,負責某一模塊的程序員不一定能清晰地判斷該模塊是否會放入多線程的環境中運行,因此:除非你能確定你的系統的瓶頸是在 StringBuffer 上,並且確定你的模塊不會運行在多線程模式下,否則還是用 StringBuffer.

3.  用好現有的類比引入新的類更重要。很多程序員在使用 StringBuffer 時是不指定其容量的(至少我見到的情況是這樣),如果這樣的習慣帶入 StringBuilder 的使用中,你將只能獲得 10 %左右的性能提升(不要忘了,你可要冒多線程的風險噢);但如果你使用指定容量的 StringBuffer ,你將馬上獲得 45% 左右的性能提升,甚至比不使用指定容量的 StirngBuilder 都快 30% 左右。

 

 

先看一個例子~~~~

public class Untitled1 {
  public Untitled1() {
  }
  public static void main(String[] args) {
    Untitled1 untitled11 = new Untitled1();
    String s1="STRING類的值是不是會變的->";
    String s2=s1;
    System.out.println(s2);
    s1+="加個試試"; //String 賦值實際上這個是NEW了一個新的對象了,S1變了
    System.out.println(s2); //S2沒有變,這是因爲S2指向的地址還是最早的s1所在的地址
 
    StringBuffer b1=new StringBuffer("StringBuffer類的值是會變的->");
    StringBuffer b2=b1;
    b2.append("加個試試");//StringBuffer賦值,操作b2還是那個對象,
    System.out.println(b1);//所以加一個字符進去b1指向的對象的值已經變了哦
  }
}

結果:
STRING類的值是不是會變的->
STRING類的值是不是會變的->
StringBuffer類的值是會變的->加個試試


摘錄:

CSDN:
這裏的"可變"和"不可變",和是不是final沒有關係

舉個例子:

String str1 = "hello";
String str2 = "world";
String str1 = str1 + str2;//這裏所做的內部操作,其實不是把str1的內容改變爲原str1+str2的內容這麼簡單, 而把創建一個新的String, 內容爲str1 + str2的內容,然後再把str1這個引用重新指向新創建的String, 這就是上面說的String不可變.

而如果是StringBuffer的話,則直接更改str1的內容,而不是先創建一個新的StringBuffer


使用 StringBuffer 主要就是在性能上的考慮。

String 是一種非常常用的數據類型,但由於 String 是不可變對象,在進行 String 的相關操作的時候會產生許多臨時的 String 對象。

而 StringBuffer 在操作上是在一個緩衝中進行的,性能當然優越得多。

不過,一般做爲簡單的字符串傳遞和其它操作,只不要改變字符串內容的操作,用 String 效率會高一些。



其他


記得以前在網上看到一篇關於java面試題的文章,裏面好像有個題就是關於StringStringBuffer的,具體的記不清了,大概內容如下:

請說出下面代碼塊存在的問題:

String tmp = “”;

for(int i=0;i

    tmp +=”x”;

}

當時網上有人只是簡單的說了要改用StringBuffer,這個存在效率問題,而沒有進一步說明,其實我也很鬱悶,是什麼效率問題呢?“顧名思義,StringBuffer之所以效率好,應該是它提供了緩存機制吧”,我想很多朋友是這樣想的吧,HOHO

當昨天晚上讀到Effective java一書的時候,我才恍然大悟,原來String是一個支持非可變性的類,這種類的特點是狀態固定(不存在任何修改對象的方法),在該對象的生存週期內,它的值是永遠不變的(它是線程安全的),它們更容易設計、實現、使用,不易出錯,更加安全。

由於String類是支持非可變性的,所以,當執行tmp +=”x”的時候,實際上是另外創建了一個對象,而tmp原來指向的那個對象就成了垃圾(當它沒有其它引用的時候),這樣的話一個循環就會產生n多對象,可以相象內存的浪費,怕怕。

 

先看一下String類中substring方法的實現

public String substring(int beginIndex, int endIndex) {

       if (beginIndex < 0) {

           throw new StringIndexOutOfBoundsException(beginIndex);

       }

       if (endIndex > count) {

           throw new StringIndexOutOfBoundsException(endIndex);

       }

       if (beginIndex > endIndex) {

           throw new StringIndexOutOfBoundsException(endIndex - beginIndex);

       }

       return ((beginIndex == 0) && (endIndex == count)) ? this :

           new String(offset + beginIndex, endIndex - beginIndex, value);

}

從藍色部份可以看出,它是重新創建了一個新的對象,符合“支持非可變性”的原則,但這卻也顯示出了非可變類的真正惟一的缺點,就是“對於每一個不同的值都要求一個單獨的對象”。

那爲什麼String要設計成非可變類呢?我覺得Stringjava中使用最爲頻繁的一個類,只有使其支持非可變性,纔有可能避免一系列的問題,比如說:

String a,b,c;

a=”test”;

b=a;

c=b;

processA(){

    ……..

}

ProcessB(){

    ……..

}

ProcessC(){

    ……..

}

String支持非可變性的時候,它們的值很好確定,不管調用哪個方法,都互不影響,如果它不支持的話,那麼我無法想象其結果。

StringBuffer做爲String的“配套類(companying class)”,它的作用就是爲了解決上述問題的,StringBuffer扮演了String的可變配套類角色。非可變類本質上是線程安全的,它們不要求做同步處理,我們可以將其共享給所有用戶,讓所有的“客戶端程序員”都可以直接使用此類而不需要做任何額外的工作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章