使用迭代器时为什么不能用集合删除元素的方法
2017-06-29 19:57
411 查看
原文地址:http://www.cnblogs.com/YYCat/p/4675084.html
由该链接引发的思考: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() 方法会在删除当前迭代对象的同时维护索引的一致性
P.S.
自我感觉就像对账一样。总奖励有10万,A持有所有的奖励领取记录(共领取了4万),B持有记录的备份。B对账的时候,突然小明从A那取走1万,A的记录更新了但B没有。
B对账的时候发现奖励还剩5万,有1万不在账上。他赶紧上报(抛异常)。(都是假设)
由该链接引发的思考: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() 方法会在删除当前迭代对象的同时维护索引的一致性
P.S.
自我感觉就像对账一样。总奖励有10万,A持有所有的奖励领取记录(共领取了4万),B持有记录的备份。B对账的时候,突然小明从A那取走1万,A的记录更新了但B没有。
B对账的时候发现奖励还剩5万,有1万不在账上。他赶紧上报(抛异常)。(都是假设)
相关文章推荐
- 为什么Iterator的remove方法可保证从源集合中安全地删除对象,而在迭代期间不能直接删除集合内元素
- java 集合元素的删除要使用迭代器(Iterator) 笔记
- 在使用迭代器遍历集合时,为何不能使用集合的remove方法?
- 使用迭代器删除集合的元素抛出异常
- Java使用迭代器遍历集合,遍历过程中可删除元素
- 如何边遍历集合边删除元素--使用Iterator中的remove()方法
- ie浏览器的不能使用remove()方法去删除。
- vector::erase方法,返回值是更新后的容器的被删除元素的后一个元素的迭代器,如果需要指向删除元素的前面一个元素的迭代器就要-1
- jQuery使用empty()方法删除元素及其所有子元素的方法
- Pycharm里面使用PIL库之后,为什么调用Image的方法不能弹出代码提示,怎样能让代码提示弹出?
- Java集合中删除元素使用Iterator
- PageCollectionView[Bug],使用Filter的时候,删除集合中的元素,会导致ArgumentOutOfRangeException
- 删除ArrayList集合中的元素(方法剖析)
- Java学习之容器上(Collection接口常用方法,Iterator接口,使用foreach循环遍历Collection集合元素,Set集合通用知识(Hashset类,hashcode()与Lin
- js使用removeChild方法动态删除div元素
- Java集合之List遍历找到匹配元素删除方法总结
- 删除一个单项链表的最中间的元素,要求时间尽可能短(不能使用两次循环)java
- 第十章 Scala 容器基础(十五):使用flatten方法来展开一个元素为集合的集合
- 05-常用对象API(集合框架-迭代器使用). 1 2 07-常用对象API(集合框架-List和Set的特点) 08-常用对象API(集合框架-List集合的常见方法) 1 2
- 关于for each循环不能直接使用集合的remove方法的原因