java 集合modcount_ArrayList中modCount的作用

在ArrayList中有个成员变量modCount,继承于AbstractList。

这个成员变量记录着集合的修改次数,也就每次add或者remove它的值都会加1。这到底有什么用呢?

先看下面一段测试代码:

packagetemp;importjava.util.ArrayList;importjava.util.List;importjava.util.Iterator;public classdemo {public static voidmain(String[] args){

List list = new ArrayList();//CopyOnWriteArrayList list = new CopyOnWriteArrayList();

list.add("a");Iterator iterator=list.iterator();while(iterator.hasNext()){

String str=(String) iterator.next();list.remove(str);}

}

}

在使用迭代器遍历集合的时候同时修改集合元素。因为ArrayList被设计成非同步的,所以理所当然会抛异常。但是该抛什么异常才能说明该问题呢?

首先得了解ArrayList的迭代器

public Iteratoriterator() {return newItr();

}

在调用list.iterator()的时候返回的是一个Itr对象,它是ArrayList中的一个内部类。

private class Itr implements Iterator{int cursor; //index of next element to return

int lastRet = -1; //index of last element returned; -1 if no such

int expectedModCount =modCount;public booleanhasNext() {return cursor !=size;

}

@SuppressWarnings("unchecked")publicE next() {

checkForComodification();int i =cursor;if (i >=size)throw newNoSuchElementException();

Object[] elementData= ArrayList.this.elementData;if (i >=elementData.length)throw newConcurrentModificationException();

cursor= i + 1;return (E) elementData[lastRet =i];

}public voidremove() {if (lastRet < 0)throw newIllegalStateException();

checkForComodification();try{

ArrayList.this.remove(lastRet);

cursor=lastRet;

lastRet= -1;

expectedModCount=modCount;

}catch(IndexOutOfBoundsException ex) {throw newConcurrentModificationException();

}

}final voidcheckForComodification() {if (modCount !=expectedModCount)throw newConcurrentModificationException();

}

}

主要关注3个点:

1、expectedModCount的初值为modCount

2、hasNext的判断条件为cursor!=size,就是当前迭代的位置不是数组的最大容量值就返回true

3、next和remove操作之前都会先调用checkForComodification来检查expectedModCount和modCount是否相等

如果没checkForComodification去检查expectedModCount与modCount相等,这个程序肯定会报ArrayIndexOutOfBoundsException

这样的异常显然不是应该出现的(这些运行时错误都是使用者的逻辑错误导致的,我们的JDK那么高端,不会出现使用错误,我们只抛出使用者造成的错误,而这个错误是设计者应该

考虑的),为了避免出现这样的异常,定义了检查。所以抛出ConcurrentModificationException异常更能说明问题。

将测试代码改成如下:

packagetemp;importjava.util.ArrayList;importjava.util.List;importjava.util.Iterator;public classdemo {public static voidmain(String[] args){

List list = new ArrayList();//CopyOnWriteArrayList list = new CopyOnWriteArrayList();

list.add("a");

list.add("b");

list.add("c");

list.add("d");

list.add("e");

Iterator iterator=list.iterator();while(iterator.hasNext()){

String str=(String) iterator.next();if(str.equals("d")){

list.remove(str);

}else{

System.out.println(str);

}

}

}

}

输出却是 a b c。

因为在删除 d 的时候cursor为4,size也变成了4。所以hasNext就返回为true了,循环结束,从而后面的元素也不会输出了。

又想,为什么不把hasNext()的判断改为cursor <=size()呢?但是我们还有可能 add()这样的话就会导致数据混乱,事实上线程安全本身就不允许读的时候被修改。

这种问题在多线程情况下,操作同一集合很容易暴露,就算改成同步的Vector问题还是会存在,需要使用CopyOnWriteArrayList。具体原因下篇博客介绍。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值