CopyOnWriteArrayList核心代码阅读



public class CopyOnWriteArrayList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
    //可重入锁,保证线程安全
    final transient ReentrantLock lock = new ReentrantLock();

    //存放数据元素的数组,只能通过get/set方法访问
    private transient volatile Object[] array;

    /**
     * Gets the array.  Non-private so as to also be accessible
     * from CopyOnWriteArraySet class.
     */
    final Object[] getArray() {
        return array;
    }

    /**
     * Sets the array.
     */
    final void setArray(Object[] a) {
        array = a;
    }

    //无参构造方法:创建一个空数组
    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }


    @SuppressWarnings("unchecked")
    private E get(Object[] a, int index) {
        return (E) a[index];
    }

    
    public E get(int index) {//获取操作属于读操作,直接通过数组下标获取数据元素,没有加锁,所以保证了性能
        return get(getArray(), index);
    }

    
    public E set(int index, E element) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();//获取到内部维护的数组
            E oldValue = get(elements, index);//通过index索引获取到元素

            if (oldValue != element) {//再判断元素是否一致
                int len = elements.length;
                Object[] newElements = Arrays.copyOf(elements, len);//不一致的话就复制一个数组
                newElements[index] = element;//将索引位置元素替换成传进来的元素
                setArray(newElements);
            } else {
                // Not quite a no-op; ensures volatile write semantics
                setArray(elements);
            }
            return oldValue;
        } finally {
            lock.unlock();
        }
    }

    
    public boolean add(E e) {
        final ReentrantLock lock = this.lock;//获取锁
        lock.lock();//加锁
        try {
            Object[] elements = getArray();//旧数组
            int len = elements.length; //获取旧数组长度
            Object[] newElements = Arrays.copyOf(elements, len + 1);//将原数组拷贝到了一个新的数组中,这个数组的长度是原数组长度加一
            newElements[len] = e;//将插入的元素放到最后
            setArray(newElements);//通过setArray方法使用新数组替换原数组的引用
            return true;
        } finally {
            lock.unlock();//释放锁
        }
    }

    
    public void add(int index, E element) {
        final ReentrantLock lock = this.lock;//获取锁
        lock.lock();//加锁
        try {
            Object[] elements = getArray(); //旧数组
            int len = elements.length;
            if (index > len || index < 0) //判断下标是否越界
                throw new IndexOutOfBoundsException("Index: "+index+
                                                    ", Size: "+len);
            Object[] newElements;//新数组  
            int numMoved = len - index;
            if (numMoved == 0)//index后面的元素个数为0的话,只需要复制一次
                newElements = Arrays.copyOf(elements, len + 1);
            else {//不为0的话,即向中间插入,就需要分两次复制到新数组了。
                newElements = new Object[len + 1];//拷贝旧数组[0,……index-1]下标的元素
                System.arraycopy(elements, 0, newElements, 0, index); //拷贝旧数组的其余元素到新数组[index+1,……length+1],刚好空出了index下标位置
                System.arraycopy(elements, index, newElements, index + 1,
                                 numMoved);
            }
            newElements[index] = element; //将插入的元素放到index下标位置
            setArray(newElements);//给array赋值
        } finally {
            lock.unlock(); //释放锁
        }
    }

    public E remove(int index) {
        final ReentrantLock lock = this.lock;//获取锁
        lock.lock();//加锁
        try {
            Object[] elements = getArray();//旧数组
            int len = elements.length;
            E oldValue = get(elements, index);
            int numMoved = len - index - 1;//计算numMoved,这个值是被删除元素的后面元素的个数
            if (numMoved == 0)//如果这个数为0,也就是删除结尾的元素,只需要进行一次数组复制,复制到长度减1的数组即可
                setArray(Arrays.copyOf(elements, len - 1));
            else {//否则,说明是删除了中间的元素,就需要分两次进行复制了
                Object[] newElements = new Object[len - 1];//完成了删除操作后,底层数组的长度减1,即没有产生空位
                System.arraycopy(elements, 0, newElements, 0, index);// 将index后面(不包含)的元素往前挪一位
               // 这样正好把index位置覆盖掉了, 相当于删除了
                System.arraycopy(elements, index + 1, newElements, index,
                                 numMoved);
                setArray(newElements);
            }
            return oldValue;
        } finally {
            lock.unlock();
        }
    }

   
    void removeRange(int fromIndex, int toIndex) {// 删除一部分元素
        final ReentrantLock lock = this.lock;//获取锁
        lock.lock();//加锁
        try {
            Object[] elements = getArray();//获取旧数组
            int len = elements.length;//获取数组长度

            if (fromIndex < 0 || toIndex > len || toIndex < fromIndex)
                throw new IndexOutOfBoundsException();//对传入参数进行正确性判断,错误则抛出异常
            int newlen = len - (toIndex - fromIndex);//新数组的长度
            int numMoved = len - toIndex;/需要移动的元素
            if (numMoved == 0)
                setArray(Arrays.copyOf(elements, newlen));如果需要删除的元素为0;则将原始数组拷贝到新数组,并重新定义引用
            else {
                Object[] newElements = new Object[newlen];//新建数组
                System.arraycopy(elements, 0, newElements, 0, fromIndex);//将需要的元素分两次拷贝到新数组
                System.arraycopy(elements, toIndex, newElements,
                                 fromIndex, numMoved);
                setArray(newElements);//将引用指向新数组
            }
        } finally {
            lock.unlock();//释放锁
        }
    }

//遍历一遍数组,把所有不需要删除的元素挑出来,放到新的数组中,变相地实现了删除元素
    public boolean removeAll(Collection<?> c) {
        if (c == null) throw new NullPointerException();//如果c为空,抛出空指针异常
        final ReentrantLock lock = this.lock;//获取锁
        lock.lock();//加锁
        try {
            Object[] elements = getArray();//获取旧数组
            int len = elements.length;//获取数组长度
            if (len != 0) {
                // 临时数组包含那些我们知道我们想要保留的元素
                int newlen = 0;
                Object[] temp = new Object[len];//新建一个数组,长度为旧数组长度
                for (int i = 0; i < len; ++i) {
                    Object element = elements[i];
                    if (!c.contains(element))//把所有不需要删除的元素挑出来,放到新的数组中
                        temp[newlen++] = element;
                }
                if (newlen != len) {
                    setArray(Arrays.copyOf(temp, newlen));
                    return true;
                }
            }
            return false;
        } finally {
            lock.unlock();
        }
    }


   
    public void clear() {// 是否将原数组的内容全部添加到新数组
        final ReentrantLock lock = this.lock;//获取锁
        lock.lock();//加锁
        try {
            setArray(new Object[0]);//将引用指向新数组
        } finally {
            lock.unlock();//释放锁
        }
    }

   
    public boolean addAll(Collection<? extends E> c) {// 是否将原数组的内容全部添加到新数组
        Object[] cs = (c.getClass() == CopyOnWriteArrayList.class) ?
            ((CopyOnWriteArrayList<?>)c).getArray() : c.toArray();//判断传入类型是否是CopyOnWriteArrayList.class类型;是的话就将c的内容存到cs,否则就将c转化为数组再存到cs;
        if (cs.length == 0)
            return false;
        final ReentrantLock lock = this.lock;//获取锁
        lock.lock();//加锁
        try {
            Object[] elements = getArray();//获取旧数组
            int len = elements.length;//获取数组长度
            if (len == 0 && cs.getClass() == Object[].class)
                setArray(cs);
            else {
                Object[] newElements = Arrays.copyOf(elements, len + cs.length);//拷贝数组元素
                System.arraycopy(cs, 0, newElements, len, cs.length);将旧数组拷贝到新数组
                setArray(newElements);
            }
            return true;
        } finally {
            lock.unlock();
        }
    }

    
    public void sort(Comparator<? super E> c) {// 排序
        final ReentrantLock lock = this.lock;//获得锁
        lock.lock();//加锁
        try {
            Object[] elements = getArray();//获取旧数组
            Object[] newElements = Arrays.copyOf(elements, elements.length);//拷贝元素到新数组
            @SuppressWarnings("unchecked") E[] es = (E[])newElements;
            Arrays.sort(es, c);
            setArray(newElements);//将引用指向新数组
        } finally {
            lock.unlock();//释放锁
        }
    }

    
    public boolean equals(Object o) {// 判断两元素是否相同
        if (o == this)
            return true;
        if (!(o instanceof List))//判断类型
            return false;

        List<?> list = (List<?>)(o);
        Iterator<?> it = list.iterator();
        Object[] elements = getArray();
        int len = elements.length;
        for (int i = 0; i < len; ++i)//比较长度
            if (!it.hasNext() || !eq(elements[i], it.next()))
                return false;
        if (it.hasNext())
            return false;
        return true;
    }

    
    public int hashCode() {//计算hash值
        int hashCode = 1;
        Object[] elements = getArray();//获取数组
        int len = elements.length;//获取长度
        for (int i = 0; i < len; ++i) {
            Object obj = elements[i];
            hashCode = 31*hashCode + (obj==null ? 0 : obj.hashCode());//计算hash值
        }
        return hashCode;
    }
}
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿究院张天师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值