探讨迭代器中为什么不能通过集合的方式删元素而是使用迭代器中的remove()方法经行删除
由该链接引发的思考:http://bbs.itheima.com/forum.php?mod=viewthread&tid=26270&mobile=1
看到这篇文章后,一副似懂非懂的样子,果断将楼主的代码拷贝到eclipse中运行了下,果断发现了些问题。
经过测试,发现总是在当集合中倒数第二个满足条件时程序才可以正常运行,否则,就会抛出ConcurrentModificationException异常
然后,我在while{it.hasNext()){和String str = (Strign)it.next()处设置了断点:——经行debug查找:
当程序抛出异常时总是执行到it.next()处发生:API中提到(在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对
列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException
。),也就是当发生了
如下图中modCount(记录了对集合修改的次数)的值不等于expectedModCount(通过迭代器对集合修改的次数)的值会抛异常。
反之,如果程序仍能正常运行的话,那么唯一的解释就是,该语句并没有执行到next这条语句块中
程序运行后发现如图:
也就是size的值等于cursor的值时,程序不会在执行while当中的内容,因此不会发生异常就结束。即——该判断标准中it.hasNext()
是否返回true的标准就是size!=cursor时成立。
最后附上网上的判断——
Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁。 Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 java.util.ConcurrentModificationException 异常。 所以 Iterator 在工作的时候是不允许被迭代的对象被改变的。但你可以使用 Iterator 本身的方法 remove() 来删除对象, Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性 |