Iterator迭代器遍历过程出现ConcurrentModificationException的原因

一、情况一

遍历的过程,使用List集合的remove方法删除某个元素,使size的值发生变化,导致 hasNext成立,从而在进行下一步的ite.next()时执行checkForComodification()方法,检查出modCount != expectedModCount成立,最后抛出throw new ConcurrentModificationException()异常。

二、调试源码核心变量的变化过程如下

在这里插入图片描述
补充:

list集合只添加了2个元素,为什么会遍历第三次呢?

这是因为在遍历第2遍的时候,list.remove()改变了list的size成员变量的大小,使size=1,导致迭代器iterator在判断是否还有下一个元素hasNext()时,cursor=2不等于siez=1成立,进入了第三次循环。


三、调式源码详细过程如下

步骤1、首先Debug来到ite.hasNext();
在这里插入图片描述
步骤2、接着F9(resume program)运行到下个断点处。
在这里插入图片描述
说明,步骤1中添加了2个元素,所以list的size=2;并且索引是从0开始的,所以cursor=0。

步骤3、接着F9(resume program)运行到下个断点处ite.next();
在这里插入图片描述
步骤4、接着F9(resume program)进入到下个断点处next()源码;
在这里插入图片描述
步骤5、接着F9(resume program)进入到下个断点处checkForComodification()源码;
在这里插入图片描述
modCount表示修改,添加集合的次数。
expectedModCount表示获取迭代器时修改次数的初始站,是在获取Iterator时赋值的。关于expectedModCount如下图所示。
在这里插入图片描述
那现在可以看到在next()源码中首先会对modCount和expectdModCount进行检查。

步骤6、接着F9(resume program)进入到下个断点处return (E) elementData[lastRet = i];
在这里插入图片描述
返回elementData[0]处的元素,也就是list中的第一个元素“e1"。

步骤7、接着F9(resume program)回到main方法的下个断点处;
在这里插入图片描述
if (element.equals(“e2”)){}条件不成立,接着执行while(ite.hasNext()){}循环。

步骤8、接着F9(resume program)回到main方法的while(ite.hasNext());
在这里插入图片描述
接着重复步骤2、执行F9(resume program)运行到下个断点处。此时的cursor=1.
在这里插入图片描述
hasNext()条件成立,返回true;
重复步骤3、接着F9(resume program)运行到下个断点处ite.next();
在这里插入图片描述
重复步骤4、接着F9(resume program)进入到下个断点处next()源码;
在这里插入图片描述
重复步骤5、接着F9(resume program)进入到下个断点处checkForComodification()源码;
在这里插入图片描述
重复步骤6、接着F9(resume program)进入到下个断点处return (E) elementData[lastRet = i];
在这里插入图片描述
返回elementData[1]处的元素,也就是list中的第一个元素“e2"。

重复步骤7、接着F9(resume program)回到main方法的下个断点处;
在这里插入图片描述
if (element.equals(“e2”)){}条件成立,接着执行list.remove(”e2“);
在这里插入图片描述
步骤9、接着F9(resume program)进入remove源码的断点处;
在这里插入图片描述
这一步modCount++;执行F8(Step Over),到下一步。
在这里插入图片描述
可以看到modCount=3,由前面mian方法开始时添加e1,e2两个元素是moumodCount=2;然后list.iterator(),对expectedModCount初始值moumodCount=2;

步骤9、接着F9(resume program)回到main方法ite.hasNext()断点处;
在这里插入图片描述
接着重复步骤2、执行F9(resume program)运行到下个断点处。此时的cursor=1.
在这里插入图片描述
调试过程的关键点就在这了,正常来说,已经没有下一个元素的,hasNext应该返回false。但由于调用了list.remove(),导致size减1,变成1,初始hasNext()中的条件返回true。

重复步骤3、接着F9(resume program)运行到下个断点处ite.next();
在这里插入图片描述
重复步骤4、接着F9(resume program)进入到下个断点处next()源码;
在这里插入图片描述
重复步骤5、接着F9(resume program)进入到下个断点处checkForComodification()源码;
在这里插入图片描述
可以看到,由于list.remove()方法导致modCount加1,此时的expectedModCount还是初始化时的2,导致条件成立,抛出throw new ConcurrentModificationException();

最后
调式到这里,就可以看到抛出ConcurrentModificationException异常的全过程和原因了。


—end

补充:学习使用iterator通过打断点调式jdk源码的来源链接如下:

https://www.iqiyi.com/v_19rwo3zlac.html#curid=14761082600_3ec318964b26c62b687013f50d84974c

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值