1 public class TestArrayListIterator {
 2     public static void main(String[] args)  {
 3         ArrayList<Integer> list = new ArrayList<Integer>();
 4         list.add(10);
 5         Iterator<Integer> iterator = list.iterator();
 6         while(iterator.hasNext()){
 7             Integer integer = iterator.next();
 8             if(integer==10)
 9                 list.remove(integer);   //注意这个地方
10         }
11     }
12 }

题主可以调试下上面的这个程序,会报运行时异常 ConcurrentModificationException

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
    at java.util.AbstractList$Itr.next(Unknown Source)
    at  com.notify.TestArrayListIterator.main(TestArrayListIterator.java:17)

在使用迭代器遍历的时候,如果使用ArrayList中的remove(int index) remove(Object o) remove(int fromIndex ,int toIndex) add等方法的时候都会修改modCount,在迭代的时候需要保持单线程的唯一操作,如果期间进行了插入或者删除,就会被迭代器检查获知,从而出现运行时异常

事实上在我们remove掉这个元素之后 ,该ArrayList的size()的值就变为了0,而此时Iterator的游标cursor是 1 ,在ArrayList迭代器的hasNext()方法中
1 public boolean hasNext() {
2             return cursor != size();
3 }

当中判断出cursor 确实不等于 size() 哭cry!!!!
然后循环又继续跑了!!!
如果我们不进行modCount和expectedModCount(创建迭代器的时候将当时的modCount赋值给expectedModCount),这个程序肯定会报ArrayIndexOutOfBoundsException,这样的异常显然不是应该出现的(这些运行时错误都是使用者的逻辑错误导致的,我们的JDK那么高端,不会出现使用错误,我们只抛出使用者造成的错误,而这个错误是设计者应该考虑的),为了避免出现这样的异常,定义了检查。

又想,为什么不把hasNext()的判断改为cursor <=size()呢?但是我们还有可能 add()这样的话就会导致数据混乱,事实上线程安全本身就不允许读的时候被修改
----------------------------------------
看看下面这篇博客可以更加深入的了解
Java ConcurrentModificationException异常原因和解决方法
--------------------------------------
使用for each 也会有上面的错误

作者:wuxinliulei
链接:https://www.zhihu.com/question/24086463/answer/64717159
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

作者:wuxinliulei
链接:https://www.zhihu.com/question/24086463/answer/64717159
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。