List中ADD()的原理

ArrayList其實就是一個長度可變的數組,看源碼就是知道,就是是一個Object[]。
ArrayList是unsynchronized。
由於底層由數組承載,那麼須要連續的內存空間,因此空間複雜度是O(n)。
若是按下標直接去get(index)或者直接add(e)到數組的尾部,那麼時間複雜度是O(1)。
若是要remove(index),或者add(index,e)那麼時間複雜度爲O(n)。
接下來看一下源碼java

/**
     * 默認初始容量空間爲10
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 空的Object數組
     */
    private static final Object[] EMPTY_ELEMENTDATA = {};

    /**
     * add存儲的數組
     */
    private transient Object[] elementData;

首先來講實例化
ArrayList(int initialCapacity);
實例化能夠直接給出數組的長度,雖然數組能夠本身擴容,可是擴容須要過程的空間複雜度應該是O(2n)由於須要拷貝一個次舊的數組。這個在後面會提到。因此當肯定數組大小的時候,好比或limit肯定了取多少數據,那麼請直接給list固定的長度。
若是用下面的夠早進行實例化,那麼初始的底層數組是一個null,是沒有長度的。數組

public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;
    }

接着看 add(),第一步先作了增量的變化this

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

而後進入ensureCapacityInternal()方法code

private void ensureCapacityInternal(int minCapacity) {
        //若是說數組沒有長度的話,須要進行長度賦值
        //第一次操做數組的話Math.max(10,1)
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //此時minCapacity = 10傳入ensureExplicitCapacity()
        ensureExplicitCapacity(minCapacity);
    }

再看ensureExplicitCapacity()方法內存

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

        // 若是說add後的長度大於現有的數組長度,說明數組應該擴容了。
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

進入grow();ci

private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
        // 先得到舊數組的長度
        int oldCapacity = elementData.length;
        //經過右移1位來實現oldCapacity/2,擴容原來的1.5倍(PS.左移一位*2,右移一位/2)
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //若是新的容量能夠放下準備add後的容量
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        //若是新擴容後大於Integer.MAX_VALUE - 8,拋出OutOfMemoryError
        //爲何會-8?javadoc說須要保留一些作head
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //肯定了新的容量後,拷貝,new 新的長度的數組,在賦值 
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

雖然List是一個可變數組,可是可變是付出了空間的代價。因此,根據實際狀況去運用。element

相關文章
相關標籤/搜索