概述
和ArrayList相比,CopyOnWriteArrayList是线程安全的,同时在for循环中删除时,CopyOnWriteArrayList是没有问题的,而ArrayList会删除不全或报错。
例如在循环删除时:
@org.junit.Test
public void t_copyWrite() {
CopyOnWriteArrayList list = new CopyOnWriteArrayList<>();
list.add("a");
list.add("ab");
// 不会报错
for (Object o : list) {
list.remove(o);
}
System.out.println("list = " + list);
ArrayList arrayList = new ArrayList<String>();
arrayList.add("a");
arrayList.add("ab");
arrayList.add("abc");
for (Object o : arrayList) {
// 会报错
arrayList.remove(o);
// 不会报错,原因后面会解释
if ("ab".equals(o)) {
arrayList.remove(o);
}
}
System.out.println("arrayList = " + arrayList);
}
for循环会经过编译转成
ArrayList arrayList = new ArrayList();
arrayList.add("a");
arrayList.add("ab");
arrayList.add("abc");
Iterator var6 = arrayList.iterator();
while(var6.hasNext()) {
Object o = var6.next();
if ("abc".equals(o)) {
arrayList.remove(o);
}
}
问题就出现在 modCount != expectedModCount 这个判断上。
// java.util.ArrayList.Itr
public boolean hasNext() {
// 不等于size就会返回true, size是在ArrayList中,是实时更新的。 如果是倒数第二个,刚好coursor==size。则返回false也就不会执行next()方法,刚好不会报错
return cursor != size;
}
// java.util.ArrayList.Itr#next
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
}
// java.util.ArrayList.Itr#checkForComodification
final void checkForComodification() {
if (modCount != expectedModCount) // modCount 还是原来的
throw new ConcurrentModificationException();
}
// java.util.ArrayList#fastRemove
private void fastRemove(int index) {
modCount++; // 修改了 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
}
再看一下CopyOnWriteArrayList
// java.util.concurrent.CopyOnWriteArrayList.COWIterator#hasNext
public boolean hasNext() {
return cursor < snapshot.length;
}
由于CopyOnWriteArrayList 摒弃了 modCount 与 expectedModCount ,每次删除后,都是重新 setArray(newElements); 所以避免了ArrayList的情况。
最后
以上就是缓慢中心为你收集整理的CopyOnWriteArrayList为何能循环删除的全部内容,希望文章能够帮你解决CopyOnWriteArrayList为何能循环删除所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复