写点什么

CopyOnWriteArrayList 源码分析 - 删除

作者:zarmnosaj
  • 2022 年 5 月 30 日
  • 本文字数:1399 字

    阅读完需:约 5 分钟

指定索引位置删除

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;        if (numMoved == 0)            setArray(Arrays.copyOf(elements, len - 1));        else {            Object[] newElements = new Object[len - 1];            System.arraycopy(elements, 0, newElements, 0, index);            System.arraycopy(elements, index + 1, newElements, index,                             numMoved);            setArray(newElements);        }        return oldValue;    } finally {        lock.unlock();    }}
复制代码


lock.lock(); 首先进行加锁


E oldValue = get(elements, index); 取得即将删除的旧数据


if (numMoved == 0) setArray(Arrays.copyOf(elements, len - 1)); 判断要删除的数据是否在数组的尾部,如果是则直接删除


Object[] newElements = new Object[len - 1]; System.arraycopy(elements, 0, newElements, 0, index); System.arraycopy(elements, index + 1, newElements, index, numMoved); setArray(newElements); 如果要删除的数据不在数组的尾部,则首先设置新数组的长度为原数组长度-1,然后从索引 0 位置开始,拷贝数组元素到尾部截止。


方法总结:


  1. 首先进行加锁

  2. 判断要删除数据的索引位置,然后选择不同的方式进行删除

  3. 最后进行解锁

  4. 整个方法使用 try-catch 进行包裹,能保证就算出现异常,锁也一定会被释放。

批量删除

源码:


public boolean removeAll(Collection<?> c) {    if (c == null) throw new NullPointerException();    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();    }}
复制代码


if (c == null) throw new NullPointerException(); 首先对要删除额元素集合进行空判断


lock.lock(); 加锁


if (len != 0) { } 判断当前数组是否有值,如果当前数组不存在值的话则直接返回


int newlen = 0; 新数组的索引位置


for (int i = 0; i < len; ++i) { } 循环判断,将不存在于删除元素集合中的数据,放到新数组中


if (!c.contains(element)) temp[newlen++] = element;判断每个元素是否存在于删除元素集合中


if (newlen != len) { setArray(Arrays.copyOf(temp, newlen)); return true; }拷贝新数组,变相的删除了不包含在 c 中的元素


方法总结:集合元素批量删除并不会逐次调用指定元素删除的方法,而是先对原数组进行循环判断,把不需要删除的元素放到一个新数组,最后得到新数组就是结果。变相的达到了删除元素的目的。

用户头像

zarmnosaj

关注

靡不有初,鲜克有终 2020.02.06 加入

成都后端混子

评论

发布
暂无评论
CopyOnWriteArrayList 源码分析-删除_5月月更_zarmnosaj_InfoQ写作社区