天天看點

Collections之Arraylist源碼解讀(六)

Collections之Arraylist源碼解讀(六)

🍁 作者:知識淺談,CSDN部落格專家,阿裡雲簽約部落客,InfoQ簽約部落客,華為雲雲享專家

📌 擅長領域:全棧工程師、爬蟲、ACM算法

💒 公衆号:知識淺談

Collections之Arraylist源碼解讀(六)總結

正菜來了⛳⛳⛳

🎈Arraylist中的方法

🍮clear()

官方解釋:Removes all of the elements from this list. The list will be empty after this call returns.

其實這段代碼,相對來說是比較簡單的,就是把ArrayList中底層的數組全部置為null,而不是把這個數組删除。

public void clear() {
    modCount++;

    // clear to let GC do its work
    for (int i = 0; i < size; i++)
        elementData[i] = null;

    size = 0;
}      

🍮addAll(Collection<? extends E> c)

這個方法的含義也比較明顯就是把Collections的對象添加到目前ArrayList中,同樣在添加之前會先判斷elementData數組中是否能夠完整添加進這個數組,就是通過調用ensureCapacityInternal這個函數進行判斷的。

public boolean addAll(Collection<? extends E> c) {
    Object[] a = c.toArray();
    int numNew = a.length;
    ensureCapacityInternal(size + numNew);  // Increments modCount
    System.arraycopy(a, 0, elementData, size, numNew);
    size += numNew;
    return numNew != 0;
}      

🍮addAll(int index, Collection<? extends E> c)

  1. 這個和上邊的很想,但是有一些差别就是,上邊的是把新的集合中的元素按順序添加到舊數組的後邊,而這個是有指定索引位置的,就是把集合中的元素按照指定索引的位置插入。
  2. 将指定集合中的所有元素插入此清單,從指定位置開始。将目前位于該位置的元素(如果有)和任何後續元素向右移動(增加它們的索引)。新元素将按照指定集合的疊代器傳回的順序出現在清單中。
public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount

        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }      

🍮removeRange(int fromIndex, int toIndex)

  1. 函數含義:這個函數的了解也比較簡單,從函數的結構上看,是移除ArrayList中的fromIndex索引到toIndex位置的元素。
  2. 但是底層的實作并不是把這些位置的元素移除,而是把toindex 位置後的元素覆寫到fromindex開始的位置到toindex位置的元素,即elementData的大小并沒有改變。
protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = size - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // clear to let GC do its work
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }      

🍮removeAll(Collection<?> c)

含義:從此清單中删除包含在指定集合中的所有元素

public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }      

從以上函數中可以看出,在删除的時候會調用requireNonNull這個函數,判斷c是不是null,如果為null,就會抛出異常。

然後調用batchRemove這個函數把elementData中的包含的c中的元素批量删除,接着看batchRemove這個函數。

🍮batchRemove(Collection<?> c, boolean complement)

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 {
            // Preserve behavioral compatibility with AbstractCollection,
            // even if c.contains() throws.
            if (r != size) {
                System.arraycopy(elementData, r,
                                 elementData, w,
                                 size - r);
                w += size - r;
            }
            if (w != size) {
                // clear to let GC do its work
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }      
for (; r < size; r++)
   if (c.contains(elementData[r]) == complement)
       elementData[w++] = elementData[r];      

🍚總結