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 會産生多餘的字元串,占用記憶體空間。