java火fouco评测_【Java】对foreach循环的思考

内部类Itr的主要函数说明

hasNext()函数

用于判断是否遍历到了集合的末尾

return cursor != size;

checkForComodification()函数

在next()和remove()函数中都会首先调用该方法来判断集合的结构是否发生变化,如果结构发生了变化,modCount就会加1,不等于expectedModCount,就会抛出异常

if (modCount !=expectedModCount)throw new ConcurrentModificationException();

next()函数

1. 先检查集合的结构有没有发生变化,若是,则抛出异常

2. 判断cursor有没有超过集合元素的个数

3. 判断cursor有没有超过ArrayList底层数组结构的大小,若是,则抛出异常

4. cursor加1,lastRet设置为当前返回元素的索引

checkForComodification();int i =cursor;if (i >=size)throw newNoSuchElementException();

Object[] elementData= ArrayList.this.elementData;if (i >=elementData.length)throw newConcurrentModificationException();

cursor= i + 1;return (E) elementData[lastRet = i];

remove()函数

1. lastRet判断是否小于0,若是,表示还未开始遍历集合,迭代器当前的索引位于集合第一个元素之前

2. 判断元素的结构有没有发生变化

3. 通过ArrayList的remove函数去除lastRet索引位置的元素,此时modCount加1

4. cursor回退到lastRet的索引位置,lastRet设为-1,expectedModCount设置为当前modCount值

if (lastRet < 0)throw newIllegalStateException();

checkForComodification();try{

ArrayList.this.remove(lastRet);

cursor=lastRet;

lastRet= -1;

expectedModCount=modCount;

}catch(IndexOutOfBoundsException ex) {throw newConcurrentModificationException();

}

3. 结合代码分析反例

条件为"1".equals(num)的情况

第一次循环,使得cursor为1,此时,符合判断条件,调用集合的remove函数删除元素,modCount加1,此时不等于expectedModCount,size减1变为1

第二次循环,调用hasNext函数,此时cursor和size都为1,判断集合中没有可遍历的元素,遍历到了末尾,结束循环,集合中为"2"的元素是没有遍历到的

最终打印出集合,结果显示为["2"]

条件为"2".equals(num)的情况

第一次循环,使得cursor为1,此时,不符合判断条件

第二次循环,hasNext调用后发现集合中还有元素,继续遍历,cursor为2,此时,符合判断条件,调用集合的remove函数删除元素,modCount加1,此时不等于expectedModCount,size减1变为1

第三次循环,hasNext函数调用的时候,cursor为2,大于size,两者也不相等,返回true,继续执行循环体,此时,会调用next函数,由于next函数首先会判断集合的结构有没有发生变化,因为第二次循环中,集合的结构已经变化了,因此会抛出ConcurrentModificationException异常

4. 为什么正例就不会出现这种问题

因为删除元素调用的是迭代器的remove函数,size变化的同时,cursor也发生了变化,不会出现cursor大于size的情况,同时,集合结构发生变化之后,迭代器的remove函数中对expectedModCount重新设值,感知到了结构的变化

最后,并发操作,需要对迭代器加锁,就不在此赘述了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值