天天看點

Collections中的内部集合類Collections中的内部集合類UnmodifiableCollectionSynchronizedCollectionCheckedCollectionEmptyListSingletonList

Collections中的内部集合類

源碼基于1.8.0_112

Collections中提供了大量的集合類,以代理的方式對現有的集合進行了功能上的修改。

總共有以下幾類集合:

Unmodifiable:不可修改的集合類

Synchronized:同步的集合類

Checked:類型安全的集合類

Empty:空集合類

Empty:隻有單個元素的集合類

由于各類以上幾類集合對List、Map、Set的實作較為相似,我們隻分析List。

原理:Collections中的内部集合類為傳入的類作為代理,改變傳入集合的行為。

UnmodifiableCollection

UnmodifiableCollection是所有Unmodifiable類的父類

UnmodifiableCollection用一個成員變量儲存傳入對象,然後為該對象提供代理

UnmodifiableList是UnmodifiableCollection的其中一個子類

UnmodifiableList也會用一個成員變量儲存傳入對象,然後為該對象提供代理

UnmodifiableCollection和UnmodifiableList各自儲存一份被代理對象的引用(指向同一個對象)。

以上都是套路,之後的集合不再介紹

UnmodifiableCollection将傳入的集合修包裝成一個不可變的集合。

代碼

/**
     * 所有Unmodifiable内部類的父類
     * @param <E>
     */
    static class MyUnmodifiableCollection<E> implements Serializable {

        // 序列化ID
        private static final long serialVersionUID = L;

        // 存儲集合類
        final Collection<? extends E> c;

        // 構造函數需要傳入一個集合類
        MyUnmodifiableCollection(Collection<? extends E> c) {
            if (c == null)
                throw new NullPointerException();
            this.c = c;
        }

        // 實作行為相同的方法,以代理的方式通路傳入的集合類
        public int size() {
            return c.size();
        }

        public boolean isEmpty() {
            return c.isEmpty();
        }

        public boolean contains(Object o) {
            return c.contains(o);
        }

        public Object[] toArray() {
            return c.toArray();
        }

        public <T> T[] toArray(T[] a) {
            return c.toArray(a);
        }

        public String toString() {
            return c.toString();
        }

        // 修改操作抛出UnsupportedOperationException異常
        public boolean add(E e) {
            throw new UnsupportedOperationException();
        }

        public boolean remove(Object o) {
            throw new UnsupportedOperationException();
        }
    }

    /**
     * List實作類
     * @param <E>
     */
    static class MyUnmodifiableList<E> extends MyUnmodifiableCollection<E> {
        private static final long serialVersionUID = -L;

        // 存儲集合
        final List<? extends E> list;

        // 需要一個傳入List來建構MyUnmodifiableList
        MyUnmodifiableList(List<? extends E> list) {
            // 調用父類構造函數
            super(list);
            // 子類指派
            this.list = list;
        }

        // 代理通路方法
        public E get(int index) {
            return list.get(index);
        }

        public int indexOf(Object o) {
            return list.indexOf(o);
        }

        public int lastIndexOf(Object o) {
            return list.lastIndexOf(o);
        }

        // 所有修改的操作,都會被禁止
        public E set(int index, E element) {
            throw new UnsupportedOperationException();
        }

        public void add(int index, E element) {
            throw new UnsupportedOperationException();
        }

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

        public boolean addAll(int index, Collection<? extends E> c) {
            throw new UnsupportedOperationException();
        }
    }
           

SynchronizedCollection

SynchronizedCollection應該算是一個比較重的的集合,他會把傳入的集合包裝成一個線程安全的集合類

SynchronizedCollection和Vector做一個比較:

1. SynchronizedCollection具有更加合理的結構

2. SynchronizedCollection可以自定義鎖對象

3. SynchronizedCollection沒有對疊代器做同步處理。Vector疊代每次的next操作都會加鎖,這樣會頻繁的加鎖,性能可想而知。我們更希望的是,在疊代前加鎖,将整個疊代過程放在同步塊中,這樣就隻會進行一次加鎖操作,SynchronizedCollection正是希望我們會這麼做。

4. 總之SynchronizedCollection更加的自由,更加推薦被使用。

總結:再需要使用同步集合的時候,我們可以選擇SynchronizedCollection和CopyOnWriteArrayList

SynchronizedCollection:一般情況下使用,注意自行同步部分方法

CopyOnWriteArrayList:集合修較少被修改的情況下使用

代碼

static class SynchronizedCollection<E> implements Serializable {

        final Collection<E> c;  // Backing Collection
        // 鎖對象
        final Object mutex;     // Object on which to synchronize

        SynchronizedCollection(Collection<E> c) {
            this.c = Objects.requireNonNull(c);
            mutex = this;
        }

        SynchronizedCollection(Collection<E> c, Object mutex) {
            this.c = Objects.requireNonNull(c);
            this.mutex = Objects.requireNonNull(mutex);
        }

        // 對操作進行加鎖處理
        public int size() {
            synchronized (mutex) {return c.size();}
        }

        // 疊代器未進行同步
        public Iterator<E> iterator() {
            return c.iterator(); // Must be manually synched by user!
        }

        public boolean add(E e) {
            synchronized (mutex) {return c.add(e);}
        }
        public boolean remove(Object o) {
            synchronized (mutex) {return c.remove(o);}
        }
    }

    static class SynchronizedList<E> extends SynchronizedCollection<E>{

        final List<E> list;

        SynchronizedList(List<E> list) {
            super(list);
            this.list = list;
        }
        SynchronizedList(List<E> list, Object mutex) {
            super(list, mutex);
            this.list = list;
        }


        public E get(int index) {
            synchronized (mutex) {return list.get(index);}
        }
        public E set(int index, E element) {
            synchronized (mutex) {return list.set(index, element);}
        }
        public void add(int index, E element) {
            synchronized (mutex) {list.add(index, element);}
        }
        public E remove(int index) {
            synchronized (mutex) {return list.remove(index);}
        }

        public ListIterator<E> listIterator() {
            return list.listIterator(); // Must be manually synched by user
        }
    }
           

CheckedCollection

CheckedCollection必須指定類型,将傳入對象包裝成一個類型安全的集合

CheckedCollection插入時會檢查類型,確定集合是類型安全的

代碼

/**
     * 類型安全的集合
     *
     * @param <E>
     */
    static class CheckedCollection<E> implements Serializable {
        private static final long serialVersionUID = L;

        final Collection<E> c;
        final Class<E> type;

        @SuppressWarnings("unchecked")
        E typeCheck(Object o) {
            if (o != null && !type.isInstance(o))
                throw new ClassCastException(badElementMsg(o));
            return (E) o;
        }

        private String badElementMsg(Object o) {
            return "Attempt to insert " + o.getClass() +
                    " element into collection with element type " + type;
        }

        // 必須制定類型
        CheckedCollection(Collection<E> c, Class<E> type) {
            this.c = Objects.requireNonNull(c, "c");
            this.type = Objects.requireNonNull(type, "type");
        }

        public int size() {
            return c.size();
        }

        public boolean remove(Object o) {
            return c.remove(o);
        }
    }

    static class CheckedList<E> extends CheckedCollection<E> {
        private static final long serialVersionUID = L;
        final List<E> list;

        CheckedList(List<E> list, Class<E> type) {
            super(list, type);
            this.list = list;
        }

        public E get(int index) {
            return list.get(index);
        }

        public E remove(int index) {
            return list.remove(index);
        }

        public E set(int index, E element) {
            return list.set(index, typeCheck(element));
        }

        // 插入時需要驗證類型
        public void add(int index, E element) {
            list.add(index, typeCheck(element));
        }
    }
           

EmptyList

EmptyList提供一個空的對象,對象不可修改。

Collections中有一個EMPTY_LIST成員變量,該變量為static

例如:某個函數傳回一個List,如果傳回的List不存在。那麼我們不應該傳回null,而是使用一個空對象代替。這時候我們可以使用

return Collections.EMPTY_LIST;

代碼

// Collections成員變量
    public static final List EMPTY_LIST = new EmptyList<>();

    /**
     * 空對象
     */
    private static class EmptyList<E> extends AbstractList<E> implements RandomAccess, Serializable {

        public int size() {return ;}
        public boolean isEmpty() {return true;}

        public E get(int index) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }
           

SingletonList

SingletonList内隻允許存儲一個元素,該元素在List初始化時确定。

代碼

/**
     * 單元素對象
     * @param <E>
     */
    private static class SingletonList<E> extends AbstractList<E> implements RandomAccess, Serializable {

        private static final long serialVersionUID = L;

        private final E element;

        // 初始化時傳入一個元素
        SingletonList(E obj) {
            element = obj;
        }

        public int size() {
            return ;
        }

        // 隻允許傳回第一個元素
        public E get(int index) {
            if (index != )
                throw new IndexOutOfBoundsException("Index: " + index + ", Size: 1");
            return element;
        }
    }
           

總結

Collections中的内部集合類對原始集合類做了一些擴充和定制,畢竟Collections算是一個工具類。