Collections中的内部集合类

本文深入分析了Java中Collections提供的各种内部集合类,包括不可修改、同步、类型安全、空及单元素集合等,并探讨了它们的实现原理及应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 = 1820017752578914078L;

        // 存储集合类
        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 = -283967356065247728L;

        // 存储集合
        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 = 1578914078182001775L;

        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 = 65247728283967356L;
        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 0;}
        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 = 3093736618740652951L;

        private final E element;

        // 初始化时传入一个元素
        SingletonList(E obj) {
            element = obj;
        }

        public int size() {
            return 1;
        }

        // 只允许返回第一个元素
        public E get(int index) {
            if (index != 0)
                throw new IndexOutOfBoundsException("Index: " + index + ", Size: 1");
            return element;
        }
    }

总结

Collections中的内部集合类对原始集合类做了一些扩展和定制,毕竟Collections算是一个工具类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值