最近在写集合类代码时,程序老是抛出ConcurrentModificationException异常,查了API文档,发现原来这是在使用迭代器遍历集合对象时修改集合对象(添加、删除、修改等操作)造成的异常。为了了解其底层的实现原理,我查看了java集合类源码,发现其底层是这样实现的:
用一个计数器modCount来累计修改次数,如每次调用集合对象的增删改方法时将累加一,使用迭代器前将modCount的值赋给expectedModCount,在迭代过程中,每次调用迭代器的next和remove方法都会检查modCount是否等于expectedModCount,这样,如果在迭代过程中修改了集合对象(抛异常前的修改操作将成功,只是修改后就抛异常了),将使得modCount的值增大,调用iterator.next或remove时将先判断到modCount不等于expectedModCount,所以将抛出异常。
所以,例如下面代码将抛出ConcurrentModificationException异常,且异常是在执行iterator.next方法时抛出的,所以实际上set已经添加了s。
while(iterator.hasNext()) {
String s = iterator.next();
s = new String("zheng");
set.add(s);
}
如果在修改set后直接跳出,将不会抛出异常,因为修改set后没有执行到iterator的next或remove方法,也就是说没有判断到modCount已经不等于expectedModCount了。最终set也将添加了s元素。
while(iterator.hasNext()) {
String s = iterator.next();
s = new String("zheng");
set.add(s);
break;
}