ArrayList的刪除實現


 

      ArrayList的刪除實現其實就是和數組添加相反的一個過程,只不過刪一個元素和刪除多個元素的實現方式略有區別,但是思路還是一樣,如下圖:

 

一、remove方法

如上,移除一個元素時,可以通過元素或者元素的索引移除,有四個步驟:

(1)判斷索引index是否越界

(2)將 index + 1 及之后的元素向前移動一位

(3)最后一個值變為null

(4)長度size - 1

將該索引以后的元素下標前移,最后一個元素置為NULL,源碼如下:

       public E remove(int index) {
            /*檢查索引是否越界*/
            rangeCheck(index);
          /*記錄集合得修改次數*/
            modCount++;
            /*獲取被刪除的元素*/
            E oldValue = elementData(index);
            /*移動的元素個數*/
            int numMoved = size - index - 1;
            if (numMoved > 0)
                /*參數:被復制的數組, 從被復制數組的第幾個元素開始復制,粘貼的目標數組,從目標數組第幾個元素開始粘貼,復制的元素個數*/
                System.arraycopy(elementData, index+1, elementData, index, numMoved);
             
            /*將最后一個元素置空,然后GC機制會回收該內存,並且ArrayList的長度-1*/
            elementData[--size] = null; 

            return oldValue;
        }
    public boolean remove(Object o) {
        /*如果刪除的元素對象為null*/
        if (o == null) {
            /*刪除ArrayList中第一個為null的元素*/
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            /*刪除ArrayList中匹配到的第一個元素*/
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
    /*不進行索引驗證,直接刪除*/
    private void fastRemove(int index) {
        modCount++;
        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
    }

二、removeAll方法

removeAll的實現方式雖然在思路上和前面一致,但是代碼實現略有不同,在移除多個元素時,會遍歷數組,先去將數組中的每個元素一一和移除元素數組里的元素匹配,

如圖:

當移除完成后,會將最后幾位(和移除元素數組長度相同)的元素置為null,源碼如下:

    public boolean removeAll(Collection<?> c) {
        /*驗證刪除Collection是否為null,若null則拋出NullPointerException*/
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }
    
    private boolean batchRemove(Collection<?> c, boolean complement) {
        /*獲取原數組*/
        final Object[] elementData = this.elementData;
        int r = 0, w = 0;
        boolean modified = false;
        try {
            /*遍歷所有元素,如果匹配到需要移除的元素,則移除該元素,並將后面未匹配到前移到移除元素位置*/
            for (; r < size; r++)
                if (c.contains(elementData[r]) == complement)
                    elementData[w++] = elementData[r];
        } finally {
            /*r != size 說明元素未完全匹配完,則將未匹配的size - r個元素粘貼到w以后的位置*/
            if (r != size) {
                System.arraycopy(elementData, r, elementData, w, size - r);            
                w += size - r;
            }
            if (w != size) {
                /*將移除完成w以后的元素置為null,由GC回收內存*/
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                /*數組長度置為w*/
                size = w;
                modified = true;
            }
        }
        return modified;
    }

三、clear方法

clear方法也是ArrayList的刪除方法之一,只不過是清除所有元素,所以只要將所有元素置為null,由GC回收內存即可

    public void clear() {
        /*記錄集合得修改次數*/
        modCount++;
        /*將每個元素置空,之后,內存會被GC回收*/
        for (int i = 0; i < size; i++)
            elementData[i] = null;
        /*元素個數置為0*/
        size = 0;
    }

 上面刪除操作,我們發現,元素是沒了,但是數組的長度並沒有變,那么ArrayList有沒有自動縮容機制了,答案是沒有,但是它提供可以實現縮容的方法,我們可以手動去觸發:

/** 將數組容量縮小至元素數量 */
public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = (size == 0)
          ? EMPTY_ELEMENTDATA
          : Arrays.copyOf(elementData, size);
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM