1. 程式人生 > 實用技巧 >String、StringBuffer與StringBuilder之間區別

String、StringBuffer與StringBuilder之間區別

概述

如下圖

String StringBuffer StringBuilder
String的值是不可變的,這就導致每次對String的操作都會生成新的String物件,不僅效率低下,而且浪費大量優先的記憶體空間 StringBuffer是可變類,和執行緒安全的字串操作類,任何對它指向的字串的操作都不會產生新的物件。每個StringBuffer物件都有一定的緩衝區容量,當字串大小沒有超過容量時,不會分配新的容量,當字串大小超過容量時,會自動增加容量 可變類,速度更快
不可變 可變 可變
執行緒安全 執行緒不安全
多執行緒操作字串 單執行緒操作字串

Java String 類——String字串常量

簡要的說, String 型別和 StringBuffer 型別的主要效能區別其實在於 String 是不可變的物件, 因此在每次對 String 型別進行改變的時候其實都等同於生成了一個新的 String 物件,然後將指標指向新的 String 物件,這樣不僅效率低下,而且大量浪費有限的記憶體空間,所以經常改變內容的字串最好不要用 String 。因為每次生成物件都會對系統性能產生影響,特別當記憶體中無引用物件多了以後, JVM 的 GC 就會開始工作,那速度是一定會相當慢的。

我們來看一下這張對 String 操作時記憶體變化的圖:

我們可以看到,初始 String 值為 “hello”,然後在這個字串後面加上新的字串 “world”,這個過程是需要重新在棧堆記憶體中開闢記憶體空間的,最終得到了 “hello world” 字串也相應的需要開闢記憶體空間,這樣短短的兩個字串,卻需要開闢三次記憶體空間,不得不說這是對記憶體空間的極大浪費。為了應對經常性的字串相關的操作,就需要使用 Java 提供的其他兩個操作字串的類—— StringBuffer 類和 StringBuilder 類來對此種變化字串進行處理。

StringBuffer 和 StringBuilder 的 3 個區別

先看看 StringBuffer 和 StringBuilder 的類結構吧:

其實很簡單,就是繼承了一個抽象的字串父類:AbstractStringBuilder。下面我們再來看看它們的三個區別。

區別1:執行緒安全

StringBuffer:執行緒安全,StringBuilder:執行緒不安全。因為 StringBuffer 的所有公開方法都是 synchronized 修飾的,而 StringBuilder 並沒有 synchronized 修飾。

StringBuffer 程式碼片段:

@Override
public synchronized StringBuffer append(String str) {
    toStringCache = null;
    super.append(str);
    return this;
}

區別2:緩衝區

StringBuffer 程式碼片段:

private transient char[] toStringCache;

@Override
public synchronized String toString() {
    if (toStringCache == null) {
        toStringCache = Arrays.copyOfRange(value, 0, count);
    }
    return new String(toStringCache, true);
}

StringBuilder 程式碼片段:

@Override
public String toString() {
    // Create a copy, don't share the array
    return new String(value, 0, count);
}

可以看出,StringBuffer 每次獲取 toString 都會直接使用快取區的 toStringCache 值來構造一個字串。

而 StringBuilder 則每次都需要複製一次字元陣列,再構造一個字串。

所以,快取衝這也是對 StringBuffer 的一個優化吧,不過 StringBuffer 的這個toString 方法仍然是同步的。

區別3:效能

既然 StringBuffer 是執行緒安全的,它的所有公開方法都是同步的,StringBuilder 是沒有對方法加鎖同步的,所以毫無疑問,StringBuilder 的效能要遠大於 StringBuffer。

總結

所以,StringBuffer 適用於用在多執行緒操作同一個 StringBuffer 的場景,如果是單執行緒場合 StringBuilder 更適合。

參考文章:

https://blog.csdn.net/itchuxuezhe_yang/article/details/89966303

https://segmentfault.com/a/1190000017909550

每天學習一點點,每天進步一點點。