從源碼和代碼相結合分析StringBuffer類及擴容原理

StringBuffer類的概念

線程安全的可變字符序列。一個類似於 String的字符串緩衝區,但不能修改。雖然在任意時間點上它都包含某種特定的字符序列,但通過某些方法調用可以改變該序列的長度和內容。

StringBuffer上的主要操作是 append 和 insert 方法,可重載這些方法,以接受任意類型的數據。每個方法都能有效地將給定的數據轉換成字符串,然後將該字符串的字符添加或插入到字符串緩衝區中。append 方法始終將這些字符添加到緩衝區的末端;而 insert 方法則在指定的點添加字符。

每個字符串緩衝區都有一定的容量。只要字符串緩衝區所包含的字符序列的長度沒有超出此容量,就無需分配新的內部緩衝區數組。如果內部緩衝區溢出,則此容量自動增大。

StringBuffer擴容的原理

源碼分析:

 	 /**
     * Constructs a string buffer with no characters in it and an
     * initial capacity of 16 characters.
     */
    public StringBuffer() {
        super(16);
    }

    /**
     * Constructs a string buffer with no characters in it and
     * the specified initial capacity.
     *
     * @param      capacity  the initial capacity.
     * @exception  NegativeArraySizeException  if the {@code capacity}
     *               argument is less than {@code 0}.
     */
    public StringBuffer(int capacity) {
        super(capacity);
    }

    /**
     * Constructs a string buffer initialized to the contents of the
     * specified string. The initial capacity of the string buffer is
     * {@code 16} plus the length of the string argument.
     *
     * @param   str   the initial contents of the buffer.
     */
    public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }

/**
     * Returns a capacity at least as large as the given minimum capacity.
     * Returns the current capacity increased by the same amount + 2 if
     * that suffices.
     * Will not return a capacity greater than {@code MAX_ARRAY_SIZE}
     * unless the given minimum capacity is greater than that.
     *
     * @param  minCapacity the desired minimum capacity
     * @throws OutOfMemoryError if minCapacity is less than zero or
     *         greater than Integer.MAX_VALUE
     */
    private int newCapacity(int minCapacity) {
        // overflow-conscious code
        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) { // overflow
            throw new OutOfMemoryError();
        }
        return (minCapacity > MAX_ARRAY_SIZE)
            ? minCapacity : MAX_ARRAY_SIZE;
    }

通過源碼分析得知,使用append()方法在字符串後面追加元素的時候,如果長度超過了該字符串存儲空間大小就需要進行擴容,需要構建新的存儲空間存儲更大的字符串,並將新生成的字符串複製過去;擴容的時候會調取一個newCapacity()方法對容量是否擴容進行判斷,所以每次擴容都會在原有容量上左移一位再加2(相當於乘以2+2)。

下面通過具體代碼來看下擴容過程

	public static void main(String[] args) {
		
		StringBuffer sb = new StringBuffer();
		
		sb.append(true);
		sb.append('a');
		sb.append("abc");
		sb.append(20);
		System.out.println("capacity==" + sb.capacity());
		sb.append("helloworld");//開始第一次擴容
		sb.append("helloworld");
		System.out.println("capacity==" + sb.capacity());
		sb.append("helloworld");//第二次擴容
		//System.out.println(sb);
		System.out.println("capacity==" + sb.capacity());
		System.out.println(sb.length());
		
		sb.insert(3, 123);
		System.out.println(sb);
	}

debug過程:

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

通過以上源碼分析和具體代碼的實現,只要掌握StringBuffer的擴容原理就很容易理解了。

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