1. 程式人生 > >StringBuilder&StringBuffer 源碼閱讀

StringBuilder&StringBuffer 源碼閱讀

簡單 else ews bst @param off star 計算 nco

StringBuilder 和 StringBuffer

StringBuilder 和 StringBuffer 都繼承了 AbstractStringBuilder 類,所有實際的字符操作都在父類實現,
主要的區別是 StringBuilder 只是簡單的調用父類方法,而 StringBuffer 的寫操作都添加了 synchronized 關鍵字。
StringBuffer 是線程安全的,而 StringBuilder 不是線程安全的。

AbstractStringBuilder

  • 屬性說明

/**
 *  可變的字符序列
 *
 * @author      Michael McCloskey
 * @author      Martin Buchholz
 * @author      Ulf Zibis
 * @since       1.5
 */
abstract class AbstractStringBuilder implements Appendable, CharSequence {
    /**
     *  用於字符存儲的字節數組
     */
    byte[] value;

    /**
     *  編碼器
     */
    byte coder;

    /**
     *  字符總數
     */
    int count;
  • 追加字符
    /**
     *  往可變字符序列中追加 boolean 值
     *
     * @param   b   一個 boolean 值
     */
    public AbstractStringBuilder append(boolean b) {
        // 嘗試進行擴容
        ensureCapacityInternal(count + (b ? 4 : 5));
        // 讀取當前字符數到局部變量表
        int count = this.count;
        // 讀取字節數組到局部變量表
        final byte[] val = value;
        // 1)如果是 LATIN1 編碼
        if (isLatin1()) {
            // 追加字符
            if (b) {
                val[count++] = 't';
                val[count++] = 'r';
                val[count++] = 'u';
                val[count++] = 'e';
            } else {
                val[count++] = 'f';
                val[count++] = 'a';
                val[count++] = 'l';
                val[count++] = 's';
                val[count++] = 'e';
            }
            // 2)如果是    UTF16 編碼
        } else {
            if (b) {
                count = StringUTF16.putCharsAt(val, count, 't', 'r', 'u', 'e');
            } else {
                count = StringUTF16.putCharsAt(val, count, 'f', 'a', 'l', 's', 'e');
            }
        }
        this.count = count;
        return this;
    }

    /**
     *  往可變字符序列中追加單個字符
     *
     * @param   c   單個字符
     */
    @Override
    public AbstractStringBuilder append(char c) {
        ensureCapacityInternal(count + 1);
        if (isLatin1() && StringLatin1.canEncode(c)) {
            value[count++] = (byte)c;
        } else {
            if (isLatin1()) {
                inflate();
            }
            StringUTF16.putCharSB(value, count++, c);
        }
        return this;
    }

    /**
     *  往可變字符序列中追加 int 值
     *
     * @param   i   一個 int 值
     */
    public AbstractStringBuilder append(int i) {
        final int count = this.count;
        final int spaceNeeded = count + Integer.stringSize(i);
        ensureCapacityInternal(spaceNeeded);
        if (isLatin1()) {
            Integer.getChars(i, spaceNeeded, value);
        } else {
            StringUTF16.getChars(i, count, spaceNeeded, value);
        }
        this.count = spaceNeeded;
        return this;
    }

    /**
     *  往可變字符序列中追加 long 值
     *
     * @param   l   一個 long 值
     */
    public AbstractStringBuilder append(long l) {
        final int count = this.count;
        final int spaceNeeded = count + Long.stringSize(l);
        ensureCapacityInternal(spaceNeeded);
        if (isLatin1()) {
            Long.getChars(l, spaceNeeded, value);
        } else {
            StringUTF16.getChars(l, count, spaceNeeded, value);
        }
        this.count = spaceNeeded;
        return this;
    }

    /**
     *  往可變字符序列中追加 float 值
     *
     * @param   f   一個浮點值
     */
    public AbstractStringBuilder append(float f) {
        FloatingDecimal.appendTo(f,this);
        return this;
    }

    /**
     *  往可變字符序列中追加 double 值
     *
     * @param   d   一個 double 值
     */
    public AbstractStringBuilder append(double d) {
        FloatingDecimal.appendTo(d,this);
        return this;
    }

    /**
     *  往可變字符序列中追加對象
     *
     * @param   obj 一個對象
     */
    public AbstractStringBuilder append(Object obj) {
        return append(String.valueOf(obj));
    }

    /**
     *  往可變字符序列中追加字符串
     *
     * @param   str 一個字符串
     */
    public AbstractStringBuilder append(String str) {
        if (str == null) {
            return appendNull();
        }
        final int len = str.length();
        ensureCapacityInternal(count + len);
        putStringAt(count, str);
        count += len;
        return this;
    }

    /**
     *  往可變字符序列中追加字符數組
     *
     * @param   str 字符數組
     */
    public AbstractStringBuilder append(char[] str) {
        final int len = str.length;
        ensureCapacityInternal(count + len);
        appendChars(str, 0, len);
        return this;
    }

    /**
     *  往可變字符序列中追加字符序列
     *
     * @param s 目標字符序列
     */
    @Override
    public AbstractStringBuilder append(CharSequence s) {
        if (s == null) {
            return appendNull();
        }
        if (s instanceof String) {
            return this.append((String)s);
        }
        if (s instanceof AbstractStringBuilder) {
            return this.append((AbstractStringBuilder)s);
        }
        return this.append(s, 0, s.length());
    }
  • 擴容過程
    /**
     *  嘗試進行擴容
     */
    private void ensureCapacityInternal(int minimumCapacity) {
        // 讀取舊容量 overflow-conscious code
        final int oldCapacity = value.length >> coder;
        // 所需最小容量 > 舊容量
        if (minimumCapacity - oldCapacity > 0) {
            // 擴容並拷貝源字節數組
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity) << coder);
        }
    }

    /**
     *  返回大於 minCapacity 的最小容量值
     *
     * @param  minCapacity  期望的最小容量
     */
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        final int oldCapacity = value.length >> coder;
            // 雙倍擴容 + 2
            int newCapacity = (oldCapacity << 1) + 2;
            // 擴容後新容量還是 < 期望最小容量,則使用期望最小容量
            if (newCapacity - minCapacity < 0) {
                newCapacity = minCapacity;
            }
            final int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
            // 一般不會走 hugeCapacity
            return newCapacity <= 0 || SAFE_BOUND - newCapacity < 0 ? hugeCapacity(minCapacity) : newCapacity;
    }

    private int hugeCapacity(int minCapacity) {
        final int SAFE_BOUND = MAX_ARRAY_SIZE >> coder;
            final int UNSAFE_BOUND = Integer.MAX_VALUE >> coder;
            if (UNSAFE_BOUND - minCapacity < 0) { // overflow
                throw new OutOfMemoryError();
            }
            return minCapacity > SAFE_BOUND
                    ? minCapacity : SAFE_BOUND;
    }
  • 插入字符
    /**
     *  在目標索引處插入 boolean 值
     *
     * @param      offset   目標索引
     * @param      b    一個 boolean 值
     */
    public AbstractStringBuilder insert(int offset, boolean b) {
        return insert(offset, String.valueOf(b));
    }

    /**
     *  在目標索引 offset 處插入字符串。
     *
     * @param      offset   目標索引
     * @param      str  字符串
     */
    public AbstractStringBuilder insert(int offset, String str) {
        // 校驗索引的合法性
        checkOffset(offset, count);
        // 目標字符為 null,則插入 'null'
        if (str == null) {
            str = "null";
        }
        // 計算目標字符長度
        final int len = str.length();
        // 嘗試擴容
        ensureCapacityInternal(count + len);
        // 目標索引處及其之後的字符數組集體右移 len 個位置
        shift(offset, len);
        count += len;
        // 插入目標字符串到指定索引 offset 處
        putStringAt(offset, str);
        return this;
    }

    /**
     *  通過數組拷貝完成子數組遷移
     *  
     * @param offset    目標索引
     * @param n
     */
    private void shift(int offset, int n) {
        System.arraycopy(value, offset << coder,
                value, offset + n << coder, count - offset << coder);
    }
  • 刪除字符
    /**
     *  刪除目標索引 start 和 end 之間的所有字符,包括起始不包括結束
     *
     * @param      start    起始索引,包含
     * @param      end  結束索引,不包含
     */
    public AbstractStringBuilder delete(int start, int end) {
        // 從堆內存加載數據到棧局部變量表
        final int count = this.count;
        if (end > count) {
            end = count;
        }
        checkRangeSIOOBE(start, end, count);
        final int len = end - start;
        if (len > 0) {
            // 從 start 索引處開始的子字符數組集體左移 len 個位置
            shift(end, -len);
            this.count = count - len;
        }
        return this;
    }

    /**
     *  刪除指定索引 index 處的單個字符
     *
     * @param       index   待移除字符的索引
     */
    public AbstractStringBuilder deleteCharAt(int index) {
        checkIndex(index, count);
        shift(index + 1, -1);
        count--;
        return this;
    }
  • 截取子字符串
    /**
     *  截取起始索引 start 到結束索引 end 之間的子字符串
     *
     * @param      start    起始索引,包括
     * @param      end  結束索引,不包括
     */
    @Override
    public CharSequence subSequence(int start, int end) {
        return substring(start, end);
    }

    /**
     *  截取起始索引 start 到結束索引 end 之間的子字符串
     *
     * @param      start    起始索引,包括
     * @param      end  結束索引,不包括
     */
    public String substring(int start, int end) {
        checkRangeSIOOBE(start, end, count);
        if (isLatin1()) {
            return StringLatin1.newString(value, start, end - start);
        }
        return StringUTF16.newString(value, start, end - start);
    }

    /**
     *  從起始索引 start 開始,截取剩余的子字符串
     *
     * @param      start    起始索引,包括
     */
    public String substring(int start) {
        return substring(start, count);
    }

StringBuilder&StringBuffer 源碼閱讀