跟蹤源碼之ArrayList源碼分析

  • add()過程

ArrayList<Integer> arrayList = new ArrayList<>();

先說一下ArrayList的構造方法,和後續的方法調用有很大關係

    /**
    * 指定初始容量的構造方法
    */
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

    /**
     *標記爲空參構造方法,後續直接擴容爲數組大小爲10
    */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    /**
     *初始化一個集合到ArrayList
    */
    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

arrayList.add(1);

  1. 裝箱
//首先進行裝箱
public static Integer valueOf(int i) {
        //看是不是在緩衝池的大小範圍內,在的話直接返回,不新建Integer
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

  2.add()方法

public boolean add(E e) {
        //先判斷加一個元素是不是就超過當前數組的大小,超過就擴容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //對數組進行賦值操作
        elementData[size++] = e;
        return true;
    }

3.ensureCapacityInternal()方法->calculateCapacity()方法->ensureExplicitCapacity()方法

這一步就是要確定最小的未填充數據的位置,並且判斷是否需要擴容(如果大於當前數組大小的話,顯然要擴容)



    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        /*如果是空參構造函數,而且沒有加入元素,elementData ==     
         DEFAULTCAPACITY_EMPTY_ELEMENTDATA就是相同的,如果說加入過元素的話就是不同的,也就是插入 
         一個元素初    始化的也是默認10個*/
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //如果指定了初始化參數是initCapacity或者Collection的話,返回當前的最小未使用的數據下標
        return minCapacity;
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        //看最小的數據capacity是不是大於當前數組的大小,如果大於就擴容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

4、grow()動態數組擴容方法

private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        //增加0.5倍進行擴容
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        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);
    }

5、最後直接賦值:elementData[size++] = e;並返回true;

get(),remove(),set()相對比較簡單,主要涉及一個驗證下標是否超出以及獲取數組內元素的操作

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