首先说一点 就是 CopyOnWriteArrayList 支持在for循环里面直接删除
上源码
private boolean remove(Object o, Object[] snapshot, int index) {
//可重入锁
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] current = getArray();
int len = current.length;
if (snapshot != current) findIndex: {
int prefix = Math.min(index, len);
for (int i = 0; i < prefix; i++) {
if (current[i] != snapshot[i] && eq(o, current[i])) {
index = i;
//跳到findIndex的标记
break findIndex;
}
}
if (index >= len)
return false;
if (current[index] == o)
break findIndex;
index = indexOf(o, current, index, len);
if (index < 0)
return false;
}
重新定义一个新的数组进行复制
Object[] newElements = new Object[len - 1];
System.arraycopy(current, 0, newElements, 0, index);
System.arraycopy(current, index + 1,
newElements, index,
len - index - 1);
setArray(newElements);
return true;
} finally {
//释放可重入锁
lock.unlock();
}
}
通过源码我们看到 在删除的操作的时候 copyOnWriteArrayList 加上了可重入锁 并且在要删除的时候直接是进行的复制操作
我们再来对比ArrayList的删除源码
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
可以看到ArrayList的remove操作的时候只是简单的在原来的数组上面进行复制,这样容易出现并发安全问题,况且还没有加锁,所以for循环里面无法用到