ArrayList的擴容機制以及常用方法源碼分析,以及面試題一篇文章就夠了

一直想記錄自己的學習過程,但始終沒有付出實際行動,說來慚愧

感謝您的關注,持續更新,歡迎留言交流~

前言:

雖然面試我們通常是講ArrayList和數組的區別,但小編覺得,我們有必要去了解一下ArrayList,在我們日常開發上,ArrayList也算得上是一種常用的集合了,接下來就和小編一起來扯下淡吧~

話不多說,直接上源碼,以下源碼基於JDK1.8 讓我們先來看看 

ArrayList list = new ArrayList();
list.add("小編是個禿頂的大叔~");
    // 默認爲 0
    private int size;

    /**
     * Appends the specified element to the end of this list.
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        // size[0] + 1 當作參數傳入方法 
        ensureCapacityInternal(size + 1);
        elementData[size++] = e;
        return true;
    }

接下來我們來看看ensureCapacityInternal()方法

思路:其實就是判斷數組是否初始化,未初始化賦初始值 10 

    // transient是用來反序列化的
    transient Object[] elementData; 

    // 定義一個空數組
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    // 默認容量爲 10
    private static final int DEFAULT_CAPACITY = 10;

    /**
    * minCapacity:當前存放值的下標 + 1(size + 1) 
    */
    private void ensureCapacityInternal(int minCapacity) {
        // 判斷elementData是不是默認的空數組
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            // 取得兩個參數中的最大值:DEFAULT_CAPACITY --> 10
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        // minCapacity = 10
        ensureExplicitCapacity(minCapacity);
    }

接下來我們看看ensureExplicitCapacity()方法:

擴容的大致整體思路:

1.判斷這個集合是否達到擴容的標準

2.若擴容之後的長度比當前的容量還小,則擴容的容量 = 當前容量(minCapaccity)

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//modCount是記錄修改次數 與線程安全有關係

        // 判斷是否達到擴容的條件: 當前容量 > 數組長度
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    private void grow(int minCapacity) {
        // 賦值以前的容量
        int oldCapacity = elementData.length;

        // 當前容量爲:old容量 + (old容量 / 2) 對於>>可以理解爲 除以2的1次方
        int newCapacity = oldCapacity + (oldCapacity >> 1);

        // 擴容後的容量 小於 當前容量
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;

        // 擴容後的容量 大於 arraylist最大容量時
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);

        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

// 小編覺得很有必要講一下這個方法:擴容之後大於ArrayList的最大容量執行的hugeCapacity方法

有這麼幾個疑問:

1.爲什麼ArrayList的數組大小(MAX_ARRAY_SIZE)是:Integer.MAX_VALUE - 8?

2.爲什麼Integer.MAX_VALUE用0x7fffffff表示?

    /**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

    /**
     * A constant holding the maximum value an {@code int} can
     * have, 2<sup>31</sup>-1.
     */
    @Native public static final int   MAX_VALUE = 0x7fffffff;

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

第一個問題:ArrayList的最大數組大小爲什麼是Integer.MAX_VALUE - 8?

剛開始小編也是到處找資料說是數組需要8 bytes去存儲它自己的大小,開始小編覺得這個回答有些敷衍,直到用翻譯工具截圖翻譯,這才解釋了源碼上這段可惡的英文,偶買噶,無形之中就暴露了小編的英文水平,請替我保密~~,哈哈哈哈哈哈

第二個問題:Integer.MAX_VALUE 爲什麼用0x7fffffff代表?

ox代表是16進制 7fffffff纔是16進制的值,簡單的說就是方便運算,計算器能理解的東西,我們不一定能理解。詳細可自行Google一下或找本基礎教材翻一下。

接下來講一點面試能扯到的實際東西。一般面試都只會問 ArrayList 的一些基本東西

1.比如ArrayList的底層實現是數組,數組的特點是:插入 刪除慢,查詢快

簡而言之就是數組刪除一個元素,需要把之後所有的元素向前移動,而查詢直接根據下標即可。

插入理解這個方法

Arrays.copyOf(原來的數組, 新的容量)

刪除理解這個方法:

例如: 現在有 1 2  3  4 這個數組集,我把 2 remove掉,後面 的 3  4 全部向前移一位 

System.arraycopy(原來的集合, 移除的元素下一位的下標, 原來的集合, 移除的元素下標,要移動的數組個數);
Object arr[] = new Object[]{1, 2, 3, 4};
System.arraycopy(arr, 2, arr, 1, 2);
arr[arr.length - 1] = null;// 移位替換之後,將最後一位數置空
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}

2.arrayList 爲什麼是線程非安全呢?顯然沒有使用關鍵字加鎖 ,擴容大小是原來的0.5倍(oldSize + oldSize/2)=newSize

最近的專題是數據結構,有什麼好的提議或者不足歡迎留言交流

關注小編,點個贊留個評論也是對小編莫大的支持,謝謝各位小哥哥,小姐姐~

後面持續更新,地中海髮型尚未形成,小編仍需努力。。。。

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