天天看點

String Builder 源碼分析

StringBuilder 與 StringBuffer 差別

StringBuilder 可變字元串,線程不太安全,但效率高,推薦使用。

StringBuffer 可變字元串,線程安全,但效率低,不推薦使用。

String 是不可變字元串,根據實時情況使用,在循環當中不要使用,因為會産生好多的沒用字元串。

通過實際代碼來展示每個方法的用法

JDK 源碼分析

首先研究它的構造器

發現它調用了父類的構造器來完成初始化。去它的父類 AbstractStringBuilder 發現

注: char[] value 用來存儲字元,count 用來記錄 char[] value 中字元的實際個數

原來 StringBuilder 和 String 一樣也是通過初始化一個字元數組來存儲字元串的。

但注意 AbstractStringBuilder 的 char[] value 并沒有用 final 修飾,那就意味着這個是可變的字元數組。那這個數組是被初始化大小的,我們如何實作可以拼接很多字元串呢?StringBuilder 不是可以無限追加( append )字元串嗎?

其實這裡用到了擴容。什麼是擴容?就是當原數組已經裝不下新添加的内容時,這個時候建立一個新數組,将原數組的内容複制到新數組中,進而達到擴容的效果。

 append 方法分析

下面我們來看一看 append 這個方法。看一看 jdk 具體是怎麼實作擴容的。

我們發現 append 其實調用的是 父類 AbstractStringBuilder 的 append 方法。在父類中重載了很多 append 方法,在這裡我以 append(String str) 為例進行講解

上面代碼的大體意思是:

如果 str 為 null,那我就添加一個 "null" 字元串。

擷取 str 的長度。

驗證是否超出容器的大小

注: Arrays.copyOf 就是 jdk 提供的一個數組複制的靜态方法

将目前 AbstractStringBuilder 的 count (char[] value 裡實際字元的個數) + len (新添加的 str 的長度) 作為 minimumCapacity,然後 minimumCapacity 和value.length (char[] value 數組的大小) 進行比較,如果 minimumCapacity 大于 value.length,則進行擴容,将原數組的資料複制到新建立的數組中。

此時AbstractStringBuilder 的 char[] value 指向了新數組的位址,原數組的位址沒有人引用,進而過後被垃圾回收機制回收。

注:   value.length << 1 ,左移一位相當與乘 2,并且這中位運算效率比較高。

可以看出新數組的大小一般為原數組大小的 2 倍 + 2,如果原數組大小的 2 倍 + 2 都小于 minimumCapacity,那麼新數組的大小為  minimumCapacity。

把 str 的内容追加到 AbstractStringBuilder 的 char[] value 中,通過數組的複制實作。(其實還是通過 System.arraycopy 這個方法實作)

修改 count (char[] value 中實際字元的個數)

傳回該方法的對象引用,進而可以實作方法鍊。

相關面試題的回答

StringBuilder 與 StringBuffer 的差別;

StringBuilder 與 String 的差別。

1. StringBuilder效率高,線程不安全,StringBuffer效率低,線程安全。

2. String是不可變字元串,StringBuilder是可變字元串。為什麼有這樣的差異,可以深入源碼去解析,比如String類内的 priver final  char  value[] 等方法的原因。

3. 如果是簡單的聲明一個字元串沒有後續過多的操作,使用 String,StringBuilder 均可,若後續對字元穿做頻繁的添加,删除操作,或者是在循環當中動态的改變字元串的長度應該用 StringBuilder。使用 String 會産生多餘的字元串,占用記憶體空間。