不少人對String和StringBuffer的區別已經很瞭解了吧,可能還有人對這兩個類的工做原理有些不清楚的地方,複習一下吧,順便牽出J2SE 5.0(文檔)裏面帶來的一個新的字符操做的類StringBuilder。那麼這個StringBuilder和StringBuffer 以及咱們最先碰見的 String 類有那些區別呢?在不一樣的場合下咱們應該用哪一個呢?我講講本身對這幾個類的一點見解,也但願你們提出意見。 簡要的說,String類型和StringBuffer類型的主要性能區別其實在於 String 是不可變的對象,所以在每次對String類型進行改變的時候其實都等同於生成了一個新的 String對象,而後將指針指向新的String對象,因此常常改變內容的字符串最好不要用 String,由於每次生成對象都會對系統性能產生影響,特別當內存中無引用對象多了之後, JVM 的GC就會開始工做,那速度是必定會至關慢的。java
這裏嘗試舉個不是很恰當的例子: api
String Str = 「abc」; 數組
For(int i = 0 ; i < 10000 ; i++){ 安全
Str + = 「def」; app
} 性能
若是是這樣的話,到這個 for 循環完畢後,若是內存中的對象沒有被 GC 清理掉的話,內存中一共有上萬個了,驚人的數目,而若是這是一個不少人使用的系統,這樣的數目就不算不少了,因此你們使用的時候必定要當心。 而若是是使用StringBuffer類則結果就不同了,每次結果都會對StringBuffer 對象自己進行操做,而不是生成新的對象,再改變對象引用。因此在通常狀況下咱們推薦使用 StringBuffer,特別是字符串對象常常改變的狀況下。而在某些特別狀況下,String 對象的字符串拼接實際上是被 JVM 解釋成了StringBuffer對象的拼接,因此這些時候 String 對象的速度並不會比 StringBuffer 對象慢,而特別是如下的字符串對象生成中, String 效率是遠要比 StringBuffer 快的: 測試
String Str = 「This is only a」 + 「 simple」 + 「 test」;ui
StringBuffer Sb = new StringBuilder(「This is only a」).append(「 simple」).append(「 test」); .net
你會很驚訝的發現,生成 String Str 對象的速度簡直太快了,而這個時候 StringBuffer 竟然速度上根本一點都不佔優點。其實這是 JVM 的一個把戲,在 JVM 眼裏,這個線程
String Str = 「This is only a」 + 「 simple」 + 「test」;
其實就是:
String Str = 「This is only a simple test」;
因此固然不須要太多的時間了。但你們這裏要注意的是,若是你的字符串是來自另外的 String 對象的話,速度就沒那麼快了,譬如:
String S2 = 「This is only a」;
String S3 = 「 simple」;
String S4 = 「 test」;
String S1 = S2 +S3 + S4;
這時候 JVM 會規規矩矩的按照原來的方式去作, S1 對象的生成速度就不像剛纔那麼快了,一下子咱們能夠來個測試做個驗證。 由此咱們獲得第一步結論:
在大部分狀況下 StringBuffer > String 而 StringBuilder 跟他們比又怎麼樣呢?先簡單介紹一下, StringBuilder 是 JDK5.0 中新增長的一個類,它跟 StringBuffer 的區別看下面的介紹: Java.lang.StringBuffer線程安全的可變字符序列。相似於 String 的字符串緩衝區,但不能修改。可將字符串緩衝區安全地用於多個線程。能夠在必要時對這些方法進行同步,所以任意特定實例上的全部操做就好像是以串行順序發生的,該順序與所涉及的每一個線程進行的方法調用順序一致。 每一個字符串緩衝區都有必定的容量。只要字符串緩衝區所包含的字符序列的長度沒有超出此容量,就無需分配新的內部緩衝區數組。若是內部緩衝區溢出,則此容量自動增大。從 JDK 5.0 開始,爲該類增添了一個單個線程使用的等價類,即 StringBuilder 。與該類相比,一般應該優先使用 StringBuilder 類,由於它支持全部相同的操做,但因爲它不執行同步,因此速度更快。 可是若是將 StringBuilder 的實例用於多個線程是不安全的。須要這樣的同步,則建議使用 StringBuffer 。 那麼下面咱們再作一個通常性推導: 在大部分狀況下 StringBuilder > StringBuffer 所以,根據這個不等式的傳遞定理: 在大部分狀況下
StringBuilder > StringBuffer > String ====================================================================
String是一個類,但倒是不可變的,因此String建立的算是一個字符串常量,StringBuffer和StringBuilder都是可變的。因此每次修改String對象的值都是新建一個對象再指向這個對象。而使用StringBuffer則是對StringBuffer對象自己進行操做。因此在字符串j常常改變的狀況下,使用StringBuffer要快得多。 但在某些狀況下: Java代碼
String S1 = 「Who」 + 「 is」 + 「 faster?」;
StringBuffer Stb = new StringBuilder(「Who」).append(「 is」).append(「 faster?」);
Java代碼
String S1 = 「Who」 + 「 is」 + 「 faster?」;
StringBuffer Stb = new StringBuilder(「Who」).append(「 is」).append(「 faster?」);
S1的素對會比Stb快得多, 是由於JVM把String對象的拼接解釋成了StringBuffer對象的拼接,其實在JVM就是:
Java代碼 String S1="Who is faster?";
Java代碼
String S1="Who is faster?";
不過若是,字符串是來自其餘對象,如:
Java代碼
String s1="Who";
String s2=" is";
String s3=" faster?";
String st=s1+s2+s3;
Java代碼
String s1="Who";
String s2=" is";
String s3=" faster?";
String st=s1+s2+s3;
這個時候,String的速度就比不上StringBuffer了。 StringBuffer和StringBuilder 在操做字符串對象,StringBuiler是最快的,StringBuffer次之,String最慢。
Java代碼
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
Java代碼
public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence
public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence
能夠看到StringBuffer和StringBuilder都繼承繼承了同一個抽象類。
Java.lang.StringBuffer線程安全的可變字符序列。一個相似於 String 的字符串緩衝區,但不能修改。雖然在任意時間點上它都包含某種特定的字符序列,但經過某些方法調用能夠改變該序列的長度和內容。 可將字符串緩衝區安全地用於多個線程。能夠在必要時對這些方法進行同步,所以任意特定實例上的全部操做就好像是以串行順序發生的,該順序與所涉及的每一個線程進行的方法調用順序一致。 每一個字符串緩衝區都有必定的容量。只要字符串緩衝區所包含的字符序列的長度沒有超出此容量,就無需分配新的內部緩衝區數組。若是內部緩衝區溢出,則此容量自動增大。 StringBuffer 上的主要操做是 append 和 insert 方法,可重載這些方法,以接受任意類型的數據。每一個方法都能有效地將給定的數據轉換成字符串,而後將該字符串的字符追加或插入到字符串緩衝區中。append 方法始終將這些字符添加到緩衝區的末端;而 insert 方法則在指定的點添加字符。 java.lang.StringBuilder一個可變的字符序列是5.0新增的。此類提供一個與 StringBuffer 兼容的 API,但不保證同步, StringBuilder的速度比StringBuffer快。該類被設計用做 StringBuffer 的一個簡易替換,用在字符串緩衝區被單個線程使用的時候(這種狀況很廣泛)。二者的方法基本相同。 若是要屢次操做字符串,使用StringBuffer和StringBuilder會提升效率,但至少在數量級超過百萬時,StringBuilder的速度纔會體現出來。