說一說java.util.Arrays$ArrayList

java.util.Arrays$ArrayList(下文:Arrays$ArrayList)是java.util.Arrays的私有靜態內部類,他實現的接口,繼承的父類幾乎和java.util.ArrayList(下文:ArrayList)相同,既然是私有的,那麼日常應該是咱們少關注的地方。本文嘗試對比一兩個他們之間的不一樣點。java

使用場景對比

構造擁有三個字符串的List
ArrayList數組

List<String> lb = new ArrayList<>(3);
        lb.add("a");
        lb.add("b");
        lb.add("c");

Arrays$ArrayListide

List<String> la = Arrays.asList("a", "b", "c");
//源碼
public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

二者都知足了需求,後者看起來比前者簡潔,除此以外二者還有什麼不一樣呢。this

增長刪除操做對比

支持的操做,spa

lb.add("d")
lb.remove("d")

不支持的操做,這將會拋出異常java.lang.UnsupportedOperationExceptioncode

la.add("d")
la.remove("d")

可見Arrays$ArrayList不容許增長也不容許刪除。blog

具體的add方法

Arrays$ArrayList類,
首先並無override父類的add方法,因此這個方法來自他的父類AbstractList
AbstractList中的add方法繼承

public boolean add(E e) {
        add(size(), e);
        return true;
    }
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }

最終調用的方法拋出了異常UnsupportedOperationException
相比較ArrayList接口

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

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

這兩個方法都在ArrayList中實現了,或者擴容而後在尾部插入,或者擴容、移動數組元素,而後插入到指定的下標位置。ip

具體的remove方法

Arrays$ArrayListremove(Object)方法繼承自AbstractList的父類AbstractCollection,其中

public boolean remove(Object o) {
        Iterator<E> it = iterator();
        if (o==null) {
            while (it.hasNext()) {
                if (it.next()==null) {
                    it.remove();
                    return true;
                }
            }
        } else {
            while (it.hasNext()) {
                if (o.equals(it.next())) {
                    it.remove();
                    return true;
                }
            }
        }
        return false;
    }

這裏使用了迭代器的方式進行刪除,看這個方法的註釋

clipboard.png
若是這個迭代器沒有實現remove方法的話,那麼這整個方法也將要拋出UnsupportedOperationException異常的。
AbstractCollectioniterator是一個抽象方法,之於Arrays$ArrayList,這個方法實現的位置仍是在AbstractList

public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
        //...省略
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            checkForComodification();

            try {
                AbstractList.this.remove(lastRet);
                if (lastRet < cursor)
                    cursor--;
                lastRet = -1;
                expectedModCount = modCount;
            } catch (IndexOutOfBoundsException e) {
                throw new ConcurrentModificationException();
            }
        }    
    }

到這裏咱們發現AbstractList實現了AbstractCollectioniterator方法,並且返回的迭代器也實現了remove方法,不是上文提到的註釋那種狀況。可是爲何刪除動做仍是不容許的呢?
具體這個迭代器的remove方法,

AbstractList.this.remove(lastRet);

可見迭代器最終也是調用容器類的remove方法的,那麼Arrays$ArrayList沒有實現remove方法,而AbstractListremove方法,以下

public E remove(int index) {
        throw new UnsupportedOperationException();
    }

所以,即便在AbstractList中使用迭代器進行刪除操做,但因爲Arrays$ArrayList沒有實現remove且繼承的remove拋出UnsupportedOperationException異常,最終在Arrays$ArrayList是不容許刪除操做的。

值得注意的是,AbstractList的迭代器是否要調用remove(int)方法是由要刪除的目標是否數組的元素決定的,若是不存在這樣的元素,則下面的代碼並不會出現異常,

List<String> la = Arrays.asList("a", "b", "c");
la.remove("e");
相關文章
相關標籤/搜索