[源碼分析]AbstractStringBuilder

[源碼分析]AbstractStringBuilder

Java中, AbstractStringBuilder是 StringBuilder 和 StringBuffer 的父類. 因此瞭解StringBuilder和StringBuffer前, 有必要先了解一下這個抽象父類.html

這裏附上另外兩篇文章的鏈接:java

StringBuilder : http://www.cnblogs.com/noKing/p/jdk8_StringBuilder.html數組

StringBuffer : http://www.cnblogs.com/noKing/p/9431618.html app

value字段

在這裏存儲字符串內容源碼分析

構造器

在構造器內當即建立一個capacity大小的數組, 做爲value字段的值.ui

擴容

 每次插入類的操做都會確保空間大小足夠. 若是不夠就會擴容, 再插入.spa

擴容是靠調用這個方法, 來確保每次有足夠的空間.3d

也就是說擴容後具體是多大, 還要根據newCapacity這個方法來定:指針

  能夠看到, 擴容策略是原先的數組長度乘以2, 而後加2. htm

若是oldLength*2+2 以後的大小足夠大了, 那麼下次的數組大小就是這個數值了.

可是oldLength*2+2以後的大小仍是不夠, 那麼就直接採用傳進來的數據做爲目標大小.(先不討論hugeCapacity)

trimToSize

trimToSize的使用結果以下:

public class AbstractStringBuilderTest {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        sb.append("hello");
        System.out.println("size:" + sb.length()); // 5
        System.out.println("capacity" + sb.capacity()); // 16
        sb.trimToSize();
        System.out.println("size:" + sb.length()); // 5
        System.out.println("capacity" + sb.capacity()); // 5
    }
}

setLength方法

詳細注意事項用下面的例子來講明:

public class AbstractStringBuilderTest {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        sb.append("hello");
        System.out.println(sb.toString()); // hello
        System.out.println("size:" + sb.length()); // 5
        System.out.println("capacity" + sb.capacity()); // 16
        sb.setLength(2);
        System.out.println(sb.toString()); // he
        System.out.println("size:" + sb.length()); // 2
        System.out.println("capacity" + sb.capacity()); // 16
        sb.setLength(20);
        System.out.println(sb.toString()); // he\0\0\0\00\0\0\00\0\0\00\0\0\0\0\0
        System.out.println("size:" + sb.length()); // 20
        System.out.println("capacity" + sb.capacity()); // 34
        sb.setLength(77);
        System.out.println("size:" + sb.length()); // 77
        System.out.println("capacity" + sb.capacity()); // 77
    }
}

  在上面這個demo中, 我用到了三次setLength. 可是每次調用後的結果都多多少少有些區別.

第1次調用: 由於setLength的參數比當前字符串的長度要小, 因此字符串被截短了, 長度也直接變爲了相應的數值.

第2次調用: 由於setLength的參數比當前字符串的長度要大, 因此多餘出來的部分用'\0'來補充.length是20. 而數組進行一次擴容就能夠hold住20這個大小, 因此就進行一次正常的擴容就好了. 正常的擴容就是原來的長度乘以2, 而後再加2, 因此是34.

第三次調用: 當前數組的長度是34, 而我setLength的參數是77.  34進行一次擴容才只是34*2+2 = 70. 由於77大於這個70, 因此capacity也就是77了.

 

一樣是參數大於當前數組的大小, 一樣是用'\0'來補充. 可是若是這個參數太大, 以致於一次擴容沒法hold住這個大小, 那麼capacity就會直接設置爲那個數值.

這段邏輯在newCapacity方法中. 代碼前面將擴容的時候粘貼過了.

charAt方法

咱們能夠看到charAt就是判斷數組越界, 來拋出異常.

返回值直接就是用的數組的下角標.

根據這個, setCharAt方法就不用多說了, 也是判斷是否越界, 而後給數組的相應位置賦值.

append方法

append方法的不少重載就是靠調用getChars方法來達到尾插的目的的. 很簡單, 就不提了.

就是appendNull方法, 很想吐槽...看完了眼前一亮....

嗯...還有append方法的bool型重載:

.....

substring

能夠看到substring底層是直接調用的new String

reverse方法

兩個指針j和k. 關於中心對稱. 從中間開始一邊向兩邊遍歷, 一邊交換. 就完成了翻轉.

總結

這個類沒什麼特別的, 但仍是稍微總結一下

1. 構造器裏當即初始化數組

2. 擴容方式爲 擴容前長度 * 2 + 2

3. 當前第2條說的不嚴謹. 首先想一想爲何擴容呢? 由於插入一個字符串的時候, 剩餘空間不足了, 因此擴容. 若是插入的這個字符串太長, 致使擴容一次也沒法容納下呢? 那麼就直接把長度設置爲 擴容前長度+ 插入的字符串長度 .

4. 大規模使用了System.arraycopy方法.

相關文章
相關標籤/搜索