foreach遍历集合遇到了一个奇怪的问题

qq_21955687 2018-04-03 10:27:20
先上图。
复习Iterator的时候遇到了foreach,用foreach遍历集合时做修改操作时会报ConcurrentModificationException,做了下测试。发现没报错。很奇怪。又做了别的测试。目前发现在移除倒数第二个元素时不会报错。百思不得其解。希望大家帮帮忙。
...全文
683 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
CrazyCoder1992 2018-04-03
  • 打赏
  • 举报
回复
引用 2 楼 qq_21955687的回复:
引用 1 楼 codeman_cdb 的回复:
在遍历list的过程中执行改变list长度的操作时应该用iterator来执行。在这个例子中,list初始长度是5,当遍历到第4个元素时会移除该元素,数组长度变成4,这样在下一次遍历时就会因下标越界保错
不对啊,第二图里我移除第四个元素,没有报错诶。
额,我之前的回答有问题。 刚看了下jdk源码,list对象有一个modCount全局变量,专门记录数组结构的修改次数,每次修改list结构modCount都会自增。 另外还有一个expectedModCount变量,记录修改次数的期望值。 当使用list.remove()方法时,modCount次数会自增,但没有同步修改expectedModCount。 而在每次遍历下一个元素之前,会校验modCount和expectedModCount是否相等,若不相等也抛上边的异常。 另外,使用list.remove()方法时,list的size属性会减一。 你的第二份代码之所以没报错,是因为移除掉第4个元素之后,游标的已遍历长度刚好等于size值,list就认为已经遍历完所有元素,没有再遍历下一个元素。因此也就没报错,而实际上最后一个元素并没有遍历到。
CrazyCoder1992 2018-04-03
  • 打赏
  • 举报
回复
用iterator.remove()不会出现这个问题,因为iterator再移除元素的时候会同步修改modCount和expectModCount的值
  • 打赏
  • 举报
回复
遍历的过程中不能进行删除操作,应该记录标志位等遍历完统一删除。
  • 打赏
  • 举报
回复
可以参考这个帖子https://blog.csdn.net/superxlcr/article/details/51534428
qq_21955687 2018-04-03
  • 打赏
  • 举报
回复
引用 1 楼 codeman_cdb 的回复:
在遍历list的过程中执行改变list长度的操作时应该用iterator来执行。在这个例子中,list初始长度是5,当遍历到第4个元素时会移除该元素,数组长度变成4,这样在下一次遍历时就会因下标越界保错
不对啊,第二图里我移除第四个元素,没有报错诶。
CrazyCoder1992 2018-04-03
  • 打赏
  • 举报
回复
在遍历list的过程中执行改变list长度的操作时应该用iterator来执行。在这个例子中,list初始长度是5,当遍历到第4个元素时会移除该元素,数组长度变成4,这样在下一次遍历时就会因下标越界保错
qq_21955687 2018-04-03
  • 打赏
  • 举报
回复
引用 3 楼 qq_18630487 的回复:
遍历的过程中不能进行删除操作,应该记录标志位等遍历完统一删除。
感谢,不过我这个问题是基于对foreach的test,发现了一个问题。
qq_21955687 2018-04-03
  • 打赏
  • 举报
回复
引用 5 楼 codeman_cdb 的回复:
引用 2 楼 qq_21955687的回复:
[quote=引用 1 楼 codeman_cdb 的回复:] 在遍历list的过程中执行改变list长度的操作时应该用iterator来执行。在这个例子中,list初始长度是5,当遍历到第4个元素时会移除该元素,数组长度变成4,这样在下一次遍历时就会因下标越界保错
不对啊,第二图里我移除第四个元素,没有报错诶。
额,我之前的回答有问题。 刚看了下jdk源码,list对象有一个modCount全局变量,专门记录数组结构的修改次数,每次修改list结构modCount都会自增。 另外还有一个expectedModCount变量,记录修改次数的期望值。 当使用list.remove()方法时,modCount次数会自增,但没有同步修改expectedModCount。 而在每次遍历下一个元素之前,会校验modCount和expectedModCount是否相等,若不相等也抛上边的异常。 另外,使用list.remove()方法时,list的size属性会减一。 你的第二份代码之所以没报错,是因为移除掉第4个元素之后,游标的已遍历长度刚好等于size值,list就认为已经遍历完所有元素,没有再遍历下一个元素。因此也就没报错,而实际上最后一个元素并没有遍历到。[/quote]重新看了源码,发现list.remove()不会做modCount是否等于exceptedModCount的判断,现在理解了。感谢!

50,639

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧