关于CopyOnWriteArrayList底层分析

//transient修饰的变量不参与序列化和反序列化
    final transient ReentrantLock lock = new ReentrantLock();// 定义一个reentrantLock锁

    private transient volatile Object[] array;     //定义一个volatile修饰的具有可见性和有序性的数组

    final Object[] getArray() {
        return array;    		//get方法 返回数组
    }

    final void setArray(Object[] a) {
        array = a;    //将当前的数组赋值为传入的数组
    }


    public CopyOnWriteArrayList() {
        setArray(new Object[0]);    //无参构造方法 默认创建一个 长度为0的Object数组
    }
 public CopyOnWriteArrayList(Collection<? extends E> c) {   //有参构造方法 传入一个collections
        Object[] elements;    //创建一个elements数组
        if (c.getClass() == CopyOnWriteArrayList.class)   //判断当前传入的数组是不是一个CopyOnWriteArrayList类型的数组
            elements = ((CopyOnWriteArrayList<?>)c).getArray();	//将传入的数组赋值给创建的elements数组
        else {
            elements = c.toArray();          //调用toarray方法 转为一个数组
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elements.getClass() != Object[].class)      
                elements = Arrays.copyOf(elements, elements.length, Object[].class);  //如果不是Object类型数组 则复制传入elements
        }
        setArray(elements); //产生的elements副本存入
    }
public E set(int index, E element) {    //set方法 传入需要set的值以及下标
        final ReentrantLock lock = this.lock;   //获取当前锁
        lock.lock();   //上锁
        try {
            Object[] elements = getArray();  //获取副本elements数组
            E oldValue = get(elements, index);   //根据传入的副本及下标获取需要改变的值

            if (oldValue != element) {  // 如果需要改变的值和 原本的值不同
                int len = elements.length;   //取出副本数组的数组长度
                Object[] newElements = Arrays.copyOf(elements, len);   //生成一个新的数组newElements 复制副本数组
                newElements[index] = element;  //改变newElements新数组中指定下标里的内容改为指定内容
                setArray(newElements); //将产生的新数组存回array
            } else {
                // Not quite a no-op; ensures volatile write semantics
                setArray(elements);  //相同则直接将副本数组传回array
            }
            return oldValue;   //返回被改变的值
        } finally {
            lock.unlock();  //解锁
        }
    }
  public boolean add(E e) {    //add方法 传入一个需要添加的数据
        final ReentrantLock lock = this.lock;  //获取当前锁
        lock.lock(); //上锁
        try {
            Object[] elements = getArray(); //获取副本elements数组
            int len = elements.length; //取出副本数组的数组长度
            Object[] newElements = Arrays.copyOf(elements, len + 1);//生成一个新的数组newElements 复制副本数组 数组长度增加一
            newElements[len] = e;  //改变newElements新数组中最后一个下标里的内容为当前需要添加的内容
            setArray(newElements);  //相同则直接将副本数组传回array
            return true;   //返回true  add添加成功
        } finally {
            lock.unlock(); //解鎖
        }
    }
 public void add(int index, E element) {   //add方法 传入一个需要添加的数据,以及指定下标
        final ReentrantLock lock = this.lock; //获取当前锁
        lock.lock(); //上锁
        try {
            Object[] elements = getArray(); //获取副本elements数组
            int len = elements.length; //取出副本数组的数组长度
            if (index > len || index < 0)  //如果需要添加数据的下标超过数组长度或者小于零
                throw new IndexOutOfBoundsException("Index: "+index+
                                                    ", Size: "+len); //抛出下标越界异常
            Object[] newElements; //获取副本elements数组
            int numMoved = len - index;//获取一个 需要添加的下标前的位置
            if (numMoved == 0) //如果是添加到第一位
                newElements = Arrays.copyOf(elements, len + 1); //生成一个新的数组newElements 复制副本数组 数组长度增加一
            else {                                              //否则
                newElements = new Object[len + 1];    //新建一个新的数组newElements 数组长度增加一
                System.arraycopy(elements, 0, newElements, 0, index); //在新数组需要添加的下标之前数据复制
                System.arraycopy(elements, index, newElements, index + 1, //在新数组需要添加的下标之后数据复制
                                 numMoved);
            }
            newElements[index] = element; //将添加的新数据 放入新数组的指定下标处
            setArray(newElements); //直接将副本数组传回array
        } finally {
            lock.unlock(); //解锁
        }
    }
  public E remove(int index) { //remove方法 根据指定传入下标remove
        final ReentrantLock lock = this.lock; //获取当前锁
        lock.lock(); //上锁
        try {
            Object[] elements = getArray(); //获取副本elements数组
            int len = elements.length; //取出副本数组的数组长度
            E oldValue = get(elements, index);  //根据传入的副本及下标获取需要改变的值
            int numMoved = len - index - 1;  //获取需要删除的下标位置
            if (numMoved == 0) //如果是删除到第一位
                setArray(Arrays.copyOf(elements, len - 1)); //生成一个新的数组newElements 复制副本数组 数组长度减少一
            else {
                Object[] newElements = new Object[len - 1];//新建一个新的数组newElements 数组长度减少一
                System.arraycopy(elements, 0, newElements, 0, index);//在新数组需要删除的下标之前数据复制
                System.arraycopy(elements, index + 1, newElements, index,
                                 numMoved); 				//在新数组需要删除的下标之后数据复制
                setArray(newElements); 	//直接将副本数组传回array
            }
            return oldValue; 	 //返回被移除的值
        } finally {
            lock.unlock(); //解锁
        }
    }
void removeRange(int fromIndex, int toIndex) { //移除一个范围内的值
        final ReentrantLock lock = this.lock; //获取当前锁
        lock.lock();  //上锁
        try {
            Object[] elements = getArray(); //获取副本elements数组
            int len = elements.length; //取出副本数组的数组长度

            if (fromIndex < 0 || toIndex > len || toIndex < fromIndex) //如果开始下标小于0或者结束下标大于数组长度,或者结束下标大于开始下标
                throw new IndexOutOfBoundsException(); //抛出下标越界异常
            int newlen = len - (toIndex - fromIndex);  //获取新数组长度
            int numMoved = len - toIndex;  // 获取需要移动的长度
            if (numMoved == 0) //如果需要移动的长度为0 
                setArray(Arrays.copyOf(elements, newlen));  //复制一个原数组副本存入array
            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 retainAll(Collection<?> c) { //传入一个集合 来保存 本集合与 传入集合的交集
        if (c == null) throw new NullPointerException(); //如果传入一个空集合则空指针
        final ReentrantLock lock = this.lock;//获取当前锁
        lock.lock(); //上锁
        try {
            Object[] elements = getArray(); //获取副本elements数组
            int len = elements.length; //取出副本数组的数组长度
            if (len != 0) {      //如果原本的数组不为0
                // temp array holds those elements we know we want to keep
                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));   //将新数组 set回array
                    return true; //返回true
                }
            }
            return false;
        } finally {
            lock.unlock();  //解锁
        }
    }
  public void clear() { 
        final ReentrantLock lock = this.lock; //获取当前锁
        lock.lock(); //上锁
        try {
            setArray(new Object[0]);  //array中放入一个空数组
        } finally {
            lock.unlock(); //解锁
        }
    }
  public boolean addAll(int index, Collection<? extends E> c) {  //将给定集合中的所有元素添加到 arraylist 中
        Object[] cs = c.toArray();   //将传入的collection变为一个数组
        final ReentrantLock lock = this.lock;  //获取当前锁
        lock.lock(); //上锁
        try {
            Object[] elements = getArray();  //获取副本elements数组
            int len = elements.length;   //取出副本数组的数组长度
            if (index > len || index < 0)  //如果插入下标大于数组长度或者插入下标小于0
                throw new IndexOutOfBoundsException("Index: "+index+   //抛出下标越界异常
                                                    ", Size: "+len);
            if (cs.length == 0)  //如果传入的数组长度为0
                return false;  //返回false
            int numMoved = len - index;  //获取需要移动的长度
            Object[] newElements;     //创建一个新的数组
            if (numMoved == 0)   //如果需要插入到下标为0的开始位置
            	newElements = Arrays.copyOf(elements, len + cs.length); //!!!!   //新的数组为elements 长度为副本数组长度和需要加入的数组长度
            else {
                newElements = new Object[len + cs.length];  //创建新数组  长度为副本数组长度和需要加入的数组长度
                System.arraycopy(elements, 0, newElements, 0, index); //将0到插入数组下标前 复制到新数组
                System.arraycopy(elements, index,
                                 newElements, index + cs.length,
                                 numMoved);      //将副本数组从插入下标开始到结束复制到新数组
            }
            System.arraycopy(cs, 0, newElements, index, cs.length); //将传入的数组从需要插入的下标复制到新数组
            setArray(newElements);  //将新数组 set回array
            return true;
        } finally {
            lock.unlock();  //解锁
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值