foreach循环ArrayList时不能使用ArrayList的增删方法之源码简析

首先,虽然这篇博文的名称是foreach循环ArrayList时不能使用ArrayList的增删方法之源码简析,但是源码简析的主要部分其实在另一篇博文(foreach迭代ArrayList时,真的不能删除元素吗?,以下简称原博文)。

本文其实是基于原博文做了点小小的扩展。所以在继续往下阅读之前,请先阅读原博文,否则可能会不太能理解我下面在说些什么!

(为什么不再自己从头分析一遍相关源码呢?一是因为我比较懒,但是最主要还是因为我觉得原博文已经分析得很好很清晰了。)

——————————————————— 手动分割线 ————————————————————

既然看到了这里,那么我就默认你已经阅读过原博文了,接下来就先解答原博文中作者在文末提出的问题。

为了方便阅读,这里再把问题贴出来:
在这里插入图片描述
其实吧,我觉得在作者提的问题中已经给出了答案:执行完这次打印,进入下一次迭代时,又产生了checkForComodification异常。

为什么又产生了checkForComodification异常?就是因为又进入了下一次迭代,又先后执行了hasNext()方法和next()方法,在next()方法中做checkForComodification()校验时,因为modCount != expectedModCount,所以抛出异常。

那么,为什么循环到倒数第二个元素时,remove一个元素不会抛出异常,而remove两个元素却抛出异常呢?

我们来反推一下,抛出ConcurrentModificationException异常是在checkForComodification()校验中,而checkForComodification()校验是在next()方法中调用的,而想要调用next()方法,就需要hasNext()方法返回true,即迭代器认为还有下一个元素。

所以,我们已经可以猜到了,循环到倒数第二个元素时remove一个元素,接下来hasNext()方法返回了false,即判断已经没有下一个元素了,所以不会再调用next()方法,也就不会再做checkForComodification()校验,所以不会抛出异常;而remove两个元素后执行hasNext()方法返回了true,即判断还有下一个元素,所以继续调用next()方法,继续调用checkForComodification()校验,进而抛出异常。

上面是我们通过反推后得出的猜想,那么到底是不是这个原因呢?接下来就看一下hasNext()方法的具体实现。
在这里插入图片描述
可以看到hasNext()方法的实现很简单,仅仅是判断 cursor 和 size 是否相等,不相等即认为还有下一个元素,只有相等时才认为没有下一个元素了。

其中,size大家都懂,表示的是ArrayList包含的元素的实际个数。cursor表示的是 index of next element to return,我们可以简单理解为迭代器指向的下一个元素的下标(简单理解)。

理解了 cursor 和 size 代表的含义后,我们来举个栗子:

List<String> list = new ArrayList<>()</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值