1 String
String:字串常數,字串長度不可變。
2 StringBuffer
StringBuffer:字串變數(Synchronized,即執行緒安全)。如果要經常對字串內容進行修改,出於效率考量最好使用StringBuffer,如果想轉成String類型,可以呼叫StringBuffer的toString()方法。
Java.lang.StringBuffer線程安全的可變字元序列。在任意時間點上它都包含某種特定的字元序列,但透過某些方法呼叫可以改變該序列的長度和內容。可將字串緩衝區安全地用於多個執行緒。
StringBuffer 上的主要操作是 append 和 insert 方法,可重載這些方法,以接受任意類型的資料。每個方法都能有效地將?定的資料轉換成字串,然後將該字串的字元追加或插入到字串緩衝區中。 append 方法始終將這些字元新增至緩衝區的末端;而 insert 方法則在指定的點新增字元。例如,如果z 引用一個目前內容是“start”的字串緩衝區對象,則此方法呼叫z.append("le") 會使字串緩衝區包含“startle”,而z.insert(4, " le") 將更改字串緩衝區,使其包含「starlet」。
3 StringBuilder
StringBuilder:字串變數(非執行緒安全)。
java.lang.StringBuilder是一個可變的字元序列,是JDK5.0新增的。此類別提供一個與 StringBuffer 相容的 API,但不保證同步。該類別被設計用作 StringBuffer 的一個簡易替換,用在字串緩衝區被單一執行緒使用的時候(這種情況很普遍)。如果可能,建議優先採用該類,因?在大多數實作中,它比 StringBuffer 要快。兩者的方法基本上相同。
在大部分情況下,StringBuilder > StringBuffer。
4 三者區別
String 類型和StringBuffer的主要性能區別:String是不可變的對象, 因此在每次對String 類型進行改變的時候,都會產生一個新的String 對象,然後將指針指向新的String對象,所以經常改變內容的字串最好不要用String ,因?每次生成對像都會對系統性能產生影響,特別當內存中無引用對像多了以後, JVM 的GC 就會開始工作,性能就會降低。
使用 StringBuffer 類別時,每次都會對 StringBuffer 物件本身進行操作,而不是產生新的物件並改變物件參考。所以多數情況下推薦使用 StringBuffer ,特別是字串物件經常改變的情況。
在某些特別情況下, String 物件的字串拼接其實是被JVM 解釋成了StringBuffer 物件的拼接,所以這些時候String 物件的速度不會比StringBuffer 物件慢,例如:
String S1 = “This is only a” + “ simple” + “ test”; StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
產生String S1 物件的速度並不比StringBuffer慢。其實在 JVM 裡,自動做了以下轉換:
String S1 = “This is only a” + “ simple” + “test”;
JVM直接把上述語句當作:
String S1 = “This is only a simple test”;
所以速度很快。但要注意的是,如果拼接的字串來自另外的String物件的話,JVM就不會自動轉換了,速度也就沒那麼快了,例如:
String S2 = “This is only a”; String S3 = “ simple”; String S4 = “ test”; String S1 = S2 +S3 + S4;
這時候,JVM 會規規矩矩的按照原來的方式去做。
在大部分情況下,StringBuffer > String。
4.StringBuffer和StringBuilder
二者幾乎沒什麼區別,基本上都是在呼叫父類別的各個方法,一個重要的區別就是StringBuffer是線程安全的,內部的大多數方法前面都有關鍵字synchronized,這樣就會有一定的效能消耗,StringBuilder是非線程安全的,所以效率要高一些。
public static void main(String[] args) throws Exception { String string = "0"; int n = 10000; long begin = System.currentTimeMillis(); for (int i = 1; i < n; i++) { string += i; } long end = System.currentTimeMillis(); long between = end - begin; System.out.println("使用String类耗时:" + between+"ms"); int n1 = 10000; StringBuffer sb = new StringBuffer("0"); long begin1 = System.currentTimeMillis(); for (int j = 1; j < n1; j++) { sb.append(j); } long end1 = System.currentTimeMillis(); long between1 = end1 - begin1; System.out.println("使用StringBuffer类耗时:" + between1+"ms"); int n2 = 10000; StringBuilder sb2 = new StringBuilder("0"); long begin2 = System.currentTimeMillis(); for (int k = 1; k < n2; k++) { sb2.append(k); } long end2 = System.currentTimeMillis(); long between2 = end2 - begin2; System.out.println("使用StringBuilder类耗时:" + between2+"ms"); }
輸出:
使用String类耗时:982ms 使用StringBuffer类耗时:2ms 使用StringBuilder类耗时:1ms
雖然這個數字每次執行都不一樣,而且每個機子的情況也不一樣,但是有幾點是確定的,但有幾類消耗的明顯比另外一String個多得多。還有一點就是,StringBuffer要比StringBuilder消耗的多,儘管相差不明顯。
5 使用策略
(1)基本原則:如果要操作少量的數據,用String ;單線程操作大量數據,用StringBuilder ;多線程操作大量數據,用StringBuffer。
(2)不要使用String類別的"+"來進行頻繁的拼接,因?那?的效能極差的,應該使用StringBuffer或StringBuilder類,這在Java的最佳化上是一條比較重要的原則。舉個例子:在使用String 的時候,拼接字串時使用「+」在JVM上形成臨時的StringBuffer對象,同時在每一個字串上都建立一個對象,拼接了兩個字串一共需要建立4個對象! (一個保存結果的String,兩個字串對象,一個暫時的StringBuffer物件)。而使用StringBuffer的話,只需建立2個物件!一個StringBuffer物件和保存最後結果的的String物件 。
(3)?了獲得更好的性能,在構造 StirngBuffer 或 StirngBuilder 時應盡可能指定它們的容量。當然,如果你操作的字串長度不超過 16 個字元就不用了。不指定容量會顯著降低效能。
(4)StringBuilder一般使用在方法內部來完成類似"+"功能,因為?是線程不安全的,所以用完以後可以丟棄。 StringBuffer主要用在全域變數中。
(5)相同情況下使用 StirngBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的效能提升,但卻要冒多執行緒不安全的風險。而在現實的模組化程式設計中,負責某一模組的程式設計師不一定能清晰地判斷該模組是否會放入多執行緒的環境中運行,因此:除非確定係統的瓶頸是在StringBuffer 上,並且確定你的模組不會運行在多執行緒模式下,才可以採用StringBuilder;否則還是用StringBuffer。
更多辨別Java中的String與StringBuffer及StringBuilder字串類別相關文章請關注PHP中文網!