ArrayList 源碼分析

描述

ArrayList 現(xiàn)實了List接口,是一個順序容器,存放元素的順序和取出元素的順序是一樣的,內(nèi)部是用<mark style="box-sizing: border-box;">數(shù)組</mark>來實現(xiàn)的,<mark style="box-sizing: border-box;">可以存放null</mark>

成員屬性

private static final int DEFAULT_CAPACITY = 10; //默認容器長度

private static final Object[] EMPTY_ELEMENTDATA = {}; //空數(shù)組,也就是new ArrayList(0)

image.png

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //也是空數(shù)組 new ArrayList()

[圖片上傳失敗...(image-f94dc8-1632339423811)]

transient Object[] elementData; //真正的用來保存元素的數(shù)組

private int size; //元素個數(shù)

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; //可以分配的最大元素個數(shù)

protected transient int modCount = 0; //被這個list內(nèi)容被修改的次數(shù),比如add,remove() 都會加+1,這個參數(shù)也是Fail-Fast機制時使用的,通過記錄modCount參數(shù)來實現(xiàn)。在面對并發(fā)的修改時,迭代器很快就會完全失敗,而不是冒著在將來某個不確定時間發(fā)生任意不確定行為的風(fēng)險

方法

add()

image.png
 private void ensureCapacityInternal(int minCapacity) {
        //這個if 只是在new ArrayList() 之后 add()就會進去
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);//默認 10 和1 比,當(dāng)然是10
        }

        ensureExplicitCapacity(minCapacity);//進去
    }

   private void ensureExplicitCapacity(int minCapacity) {
        modCount++; //發(fā)送修改 modCount+1

        // overflow-conscious code
        if (minCapacity - elementData.length > 0) // minCapacity 是否大于原來的容器長度,這個是關(guān)鍵判斷
            grow(minCapacity); //擴容全靠它了了,哈哈
    }

  private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length; //保存原容器的長度
        int newCapacity = oldCapacity + (oldCapacity >> 1); //新的容器長度 = 原容器的長度 + 原容器的長度的一半
        if (newCapacity - minCapacity < 0) //新的容器長度是否小于傳進來的長度
            newCapacity = minCapacity; //新的容器長度 = 傳進來的長度
        if (newCapacity - MAX_ARRAY_SIZE > 0) //新的容器長度大于 Integer.MAX_VALUE - 8 ?
            newCapacity = hugeCapacity(minCapacity); //大于則是Integer.MAX_VALUE
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity); //進行數(shù)組拷貝,yes yes yes 
    }

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

set()

    public E set(int index, E element) {
        rangeCheck(index); //判斷是否越界

        E oldValue = elementData(index);  //保存舊值用于返回
        elementData[index] = element; //設(shè)置指定位置的指定值
        return oldValue; //返回舊值
    }

    private void rangeCheck(int index) {
        if (index >= size) // index >=size 就拋異常
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

get()

    public E get(int index) {
        rangeCheck(index); //判斷是否越界

        return elementData(index); //取出指定位置的值
    }

    private void rangeCheck(int index) {
        if (index >= size) // index >=size 就拋異常
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

remove()

    public E remove(int index) {
        rangeCheck(index);  //判斷index 是否越界

        modCount++; //修改次數(shù) + 1 
        E oldValue = elementData(index);  //取出舊值,用于返回

        int numMoved = size - index - 1; 

        //這個看我下面的圖
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);

        elementData[--size] = null; // clear to let GC do its work //用于gc回收

        return oldValue; //返回舊值
    }

    private void rangeCheck(int index) {
        if (index >= size) // index >=size 就拋異常
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

image.png

trimToSize()

   public void trimToSize() {
        modCount++; //修改次數(shù) + 1 
        if (size < elementData.length) { //元素個數(shù)是否小于于數(shù)組的容量
            elementData = (size == 0)  // 元素個數(shù)==0
              ? EMPTY_ELEMENTDATA //賦值空數(shù)組
              : Arrays.copyOf(elementData, size);//否則拷貝一個元素個數(shù)長度的數(shù)組
        }
    }

indexOf() 記得是用對象的equals來判斷的

public int indexOf(Object o) {
        if (o == null) { //因為可以存null 所以需要判斷是否是個null
            for (int i = 0; i < size; i++)
                if (elementData[i]==null) //是null 返回
                    return i;
        } else {
            for (int i = 0; i < size; i++)
                if (o.equals(elementData[i])) //equals 
                    return i;
        }
        return -1;
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容