AbstractStringBuilder源碼分析

抽象類AbstractStringBuilder實現了接口AppendableCharSequence,接口Appendable中有三個重載的append方法,專門來處理字符串的添加操作。

Appendable append(CharSequence csq) throws IOException;
Appendable append(CharSequence csq, int start, int end) throws IOException;
Appendable append(char c) throws IOException;

AbstractStringBuilder中有兩個重要的字段,value[]count。value是用來字符存儲的,count記錄value實際使用的字符數。比如value = new char[100],將’a’、‘b’、'c’放入value中,此時count=3。

char[] value;
int count;

對應的,AbstractStringBuilder中有兩個方法分別來獲取value的長度和實際使用的長度count,value的長度其實就是容量。getValue方法可以獲取value[],此方法被final修飾,不可被子類重寫。

@Override
public int length() {
    return count;
}

public int capacity() {
    return value.length;
}

final char[] getValue() {
    return value;
}

AbstractStringBuilder有兩個構造方法,其中無參構造方法是爲了子類的序列化,有參構造傳入了一個整數來構造一個指定容量的字符數組,並賦值給value。

AbstractStringBuilder() {
}

AbstractStringBuilder(int capacity) {
    value = new char[capacity];
}

接下來就是對容量的操作。

ensureCapacity方法確保value的容量至少是指定容量,如果指定容量大小比value原來的容量大小大就重新創建一個數組賦值給value。此方法在append方法的操作中很重要。

新數組的容量由newCapacity方法確定,首先擴容至原容量的2倍加2,這樣擴容可能是因爲如果通過有參構造方法構造一個容量爲0的字符串,那麼僅僅乘以2容量永遠都爲0。如果擴容2倍加2還是達不到指定的容量,那麼就直接擴容至指定的容量,否則的話就是繼續用該容量。

但此時就需要考慮該容量是否超出了int值的範圍,是否超出了數組的最大容量。int數值溢出會變爲負數,數組的最大容量是Integer的最大值減8,減8是因爲數組需要存儲一些額外的頭信息,並且這些信息需要的容量不會超過8。

如果新容量超出int值範圍或者超出數組最大容量,就在指定容量和數組最大容量中選擇最大的作爲新數組的容量。

public void ensureCapacity(int minimumCapacity) {
    if (minimumCapacity > 0)
        ensureCapacityInternal(minimumCapacity);
}

private void ensureCapacityInternal(int minimumCapacity) {
    if (minimumCapacity - value.length > 0) {
        value = Arrays.copyOf(value,
                              newCapacity(minimumCapacity));
    }
}

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

private int newCapacity(int minCapacity) {
    int newCapacity = (value.length << 1) + 2;
    if (newCapacity - minCapacity < 0) {
        newCapacity = minCapacity;
    }
    return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
        ? hugeCapacity(minCapacity)
        : newCapacity;
}

private int hugeCapacity(int minCapacity) {
    if (Integer.MAX_VALUE - minCapacity < 0) { 
        throw new OutOfMemoryError();
    }
    return (minCapacity > MAX_ARRAY_SIZE)
        ? minCapacity : MAX_ARRAY_SIZE;
}

trimToSize()方法是將字符串的容量降爲已被使用的容量大小。

public void trimToSize() {
    if (count < value.length) {
        value = Arrays.copyOf(value, count);
    }
}

容量可以被改變,字符串的長度也可以被改變,調用Array的fill方法填充數組並將count值設爲新的長度。但要保證新的長度合法。

public void setLength(int newLength) {
    if (newLength < 0)
        throw new StringIndexOutOfBoundsException(newLength);
    ensureCapacityInternal(newLength);

    if (count < newLength) {
        Arrays.fill(value, count, newLength, '\0');
    }

    count = newLength;
}

然後就是對字符進行操作的方法,charAt方法是重寫CharSequence的方法。

public char charAt(int index)public int codePointAt(int index)public int codePointBefore(int index)public int codePointCount(int beginIndex, int endIndex)public int offsetByCodePoints(int index, int codePointOffset)public void setCharAt(int index, char ch)

getChars方法可以將調用該方法的字符串複製到指定的字符數組中,將value的[srcBegin, srcEnd)複製到ts數組的[dstBegin, dstBegin+value.length)中。

public void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
{
    if (srcBegin < 0)
        throw new StringIndexOutOfBoundsException(srcBegin);
    if ((srcEnd < 0) || (srcEnd > count))
        throw new StringIndexOutOfBoundsException(srcEnd);
    if (srcBegin > srcEnd)
        throw new StringIndexOutOfBoundsException("srcBegin > srcEnd");
    System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

接下來是一系列的append方法,在字符串後面添加字符串。其中appendNull就是在字符串後面添加"null",append(boolean b)就是在字符串後面添加"true"或"false",append(int i)就是在字符串後面添加i的字符串。

public AbstractStringBuilder append(Object obj);
public AbstractStringBuilder append(String str);
public AbstractStringBuilder append(StringBuffer sb);
AbstractStringBuilder append(AbstractStringBuilder asb);
public AbstractStringBuilder append(CharSequence s);
private AbstractStringBuilder appendNull();
public AbstractStringBuilder append(CharSequence s, int start, int end);
public AbstractStringBuilder append(char[] str);
public AbstractStringBuilder append(char str[], int offset, int len);
public AbstractStringBuilder append(boolean b);
public AbstractStringBuilder append(char c);
public AbstractStringBuilder append(int i);
public AbstractStringBuilder append(long l);
public AbstractStringBuilder append(float f);
public AbstractStringBuilder append(double d);
public AbstractStringBuilder appendCodePoint(int codePoint);

還有在字符串中間插入字符串的insert方法。核心就是首先進行擴容,然後將value指定位置之後的字符向後移動給被插入的字符串空出位置,最後插入字符串。

public AbstractStringBuilder insert(int index, char[] str, int offset, int len);
public AbstractStringBuilder insert(int offset, Object obj);
public AbstractStringBuilder insert(int offset, String str);
public AbstractStringBuilder insert(int offset, char[] str);
public AbstractStringBuilder insert(int dstOffset, CharSequence s);
public AbstractStringBuilder insert(int dstOffset, CharSequence s, int start, int end);
public AbstractStringBuilder insert(int offset, boolean b);
public AbstractStringBuilder insert(int offset, char c);
public AbstractStringBuilder insert(int offset, int i);
public AbstractStringBuilder insert(int offset, long l);
public AbstractStringBuilder insert(int offset, float f);
public AbstractStringBuilder insert(int offset, double d);

delete方法可以刪除字符串的子串。

public AbstractStringBuilder delete(int start, int end);
public AbstractStringBuilder deleteCharAt(int index);

replace方法替換字符串的子串。

public AbstractStringBuilder replace(int start, int end, String str);

substring方法返回字符串的子串。

public String substring(int start);
public CharSequence subSequence(int start, int end);
public String substring(int start, int end);

indexOf方法返回子串在字符串中的位置。

public int indexOf(String str);
public int indexOf(String str, int fromIndex);
public int lastIndexOf(String str);
public int lastIndexOf(String str, int fromIndex);

resverse方法將字符串反轉,以後可以借鑑該方法的實現,從中間開始

public AbstractStringBuilder reverse() {
    boolean hasSurrogates = false;
    int n = count - 1;
    for (int j = (n-1) >> 1; j >= 0; j--) {
        int k = n - j;
        char cj = value[j];
        char ck = value[k];
        value[j] = ck;
        value[k] = cj;
        if (Character.isSurrogate(cj) ||
            Character.isSurrogate(ck)) {
            hasSurrogates = true;
        }
    }
    if (hasSurrogates) {
        reverseAllValidSurrogatePairs();
    }
    return this;
}

private void reverseAllValidSurrogatePairs() {
    for (int i = 0; i < count - 1; i++) {
        char c2 = value[i];
        if (Character.isLowSurrogate(c2)) {
            char c1 = value[i + 1];
            if (Character.isHighSurrogate(c1)) {
                value[i++] = c1;
                value[i] = c2;
            }
        }
    }
}

最後,該類提供了一個抽象的toString方法,該方法繼承自CharSequence接口。

@Override
public abstract String toString();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章