Java 詳解String、StringBuffer和StringBuilder

String StringBuffer StringBuilder
速度慢 速度快 速度最快
不可變 可變 可變
線程安全 線程不安全
多線程操作字符串 單線程操作字符串

一、String

String:字符串常量,字符串長度不可變。Java中String是immutable(不可變)的。

String類的包含如下定義:

/** The value is used for character storage. */
private final char value[];
 
/** The offset is the first index of the storage that is used. */
private final int offset;
 
/** The count is the number of characters in the String. */
private final int count;

用於存放字符的數組被聲明爲final的,因此只能賦值一次,不可再更改。

例 :

  我們可以看到,初始String值爲“hello”,然後在這個字符串後面加上新的字符串“world”,這個過程是需要重新在棧堆內存中開闢內存空間的,最終得到了“hello world”字符串也相應的需要開闢內存空間,這樣短短的兩個字符串,卻需要開闢三次內存空間,不得不說這是對內存空間的極大浪費爲了應對經常性的字符串相關的操作,谷歌引入了兩個新的類——StringBuffer類和StringBuild類來對此種變化字符串進行處理。

三者的繼承結構

二、StringBuffer(JDK1.0)

  StringBuffer:字符串變量(Synchronized,即線程安全)。如果要頻繁對字符串內容進行修改,出於效率考慮最好使用StringBuffer,如果想轉成String類型,可以調用StringBuffer的toString()方法。

  Java.lang.StringBuffer線程安全的可變字符序列。在任意時間點上它都包含某種特定的字符序列,但通過某些方法調用可以改變該序列的長度和內容。可將字符串緩衝區安全地用於多個線程。

三、StringBuilder(JDK5.0)

  StringBuilder:字符串變量(非線程安全)。在內部,StringBuilder對象被當作是一個包含字符序列的變長數組。

  java.lang.StringBuilder是一個可變的字符序列,是JDK5.0新增的。此類提供一個與 StringBuffer 兼容的 API,但不保證同步。該類被設計用作 StringBuffer 的一個簡易替換,用在字符串緩衝區被單個線程使用的時候(這種情況很普遍)。

其構造方法如下:

構造方法 描述
StringBuilder() 創建一個容量爲16的StringBuilder對象(16個空元素)
StringBuilder(CharSequence cs) 創建一個包含cs的StringBuilder對象,末尾附加16個空元素
StringBuilder(int initCapacity) 創建一個容量爲initCapacity的StringBuilder對象
StringBuilder(String s) 創建一個包含s的StringBuilder對象,末尾附加16個空元素

四、三者區別

  1、String是字符串常量,而StringBuffer和StringBuilder是字符串變量。由String創建的字符內容是不可改變的,而由StringBuffer和StringBuidler創建的字符內容是可以改變的。

  2、StringBuffer是線程安全的,而StringBuilder是非線程安全的。StringBuilder是從JDK 5開始,爲StringBuffer類補充的一個單線程的等價類。

五、 使用策略

  • 基本原則:如果要操作少量的數據,用String ;單線程操作大量數據,用StringBuilder ;多線程操作大量數據,用StringBuffer。 -

  • 不要使用String類的"+"來進行頻繁的拼接,因爲那樣的性能極差的,應該使用StringBuffer或StringBuilder類,這在Java的優化上是一條比較重要的原則。例如:

String result = "";
for (String s : hugeArray) {
    result = result + s;
}
 
// 使用StringBuilder
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {
    sb.append(s);
}
String result = sb.toString();

當出現上面的情況時,顯然我們要採用第二種方法,因爲第一種方法,每次循環都會創建一個String result用於保存結果,除此之外二者基本相同(對於jdk1.5及之後版本)

  • 爲了獲得更好的性能,在構造 StringBuffer 或 StringBuilder 時應儘可能指定它們的容量。當然,如果你操作的字符串長度(length)不超過 16 個字符就不用了,當不指定容量(capacity)時默認構造一個容量爲16的對象。不指定容量會顯著降低性能。

  • StringBuilder一般使用在方法內部來完成類似"+"功能,因爲是線程不安全的,所以用完以後可以丟棄。StringBuffer主要用在全局變量中。

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


參考文章 :

  • https://blog.csdn.net/kingzone_2008/article/details/9220691
  • https://blog.csdn.net/itchuxuezhe_yang/article/details/89966303
  • https://juejin.im/post/5a5d5c66f265da3e261bf46c
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章