List删除时报错问题(ConcurrentModificationException)

以下内容以ArrayList源码解读


目录

 

一.问题

二.解析

三.结论


一.问题

集合在遍历删除是可能会报ConcurrentModificationException异常

二.解析

1.要了解这个问题首先要知道引起的原因,是List中的modCount与迭代器中expectedModCount 值不一致导致的

2.了解modCount和expectedModCount

(1.)在AbstractList中定义了 protected transient int modCount = 0; 用这个变量记录该集合被修改的次数,以下这些操作会导致modCount++

  • add (用到了ensureCapacityInternal->ensureExplicitCapacity方法进行扩容判断,而此实现modcount++)
  • remove
  • clear
ArrayList增加方法
ArrayList删除方法
ArrayList清空方法

(2)在调用集合iterator方法时,返回内部类Iterator实例是,迭代器中的expectedModCount会被赋为modCount的值为初始值

如图示

在调用迭代器遍历或删除前会校验这两个值是否一致,不一致是抛出ConcurrentModificationException错误

三.结论

1.为什么不能在迭代器中/foreach中直接删除或添加元素
foreach遍历集合,编译后发现就是使用迭代器遍历的(数组则是普通for循环实现)。在迭代器中直接(调用集合的方法)删除或是添加元素,会导致集合中modCount增加,而迭代器中expectedModCount在初次实例时与modCount相等,此时modCount
修改了而expectedModCount未修改,迭代器下次遍历时会调用checkForComodification方法校验modCount和expectedModCount是否相同,不同抛出ConcurrentModificationException错误。

2.如何实现删除
(1)用不同for循环,直接用list的删除方法删除。此时未涉及到迭代器,不存在报错情况;但注意正序删除的下标问题,倒序删除不存在,容易把控(推荐)
(2)用迭代器遍历,用迭代器的删除方法。迭代器的删除方法也是调用了list的删除方法,也会引起modCount++,但是迭代器会有expectedModCount = modCount这一步对齐操作,保证删除成功且不出错(推荐)

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用和提供了关于ConcurrentModificationException异常的信息。ConcurrentModificationExceptionJava集合框架中的一个异常,通常在使用迭代器遍历集合出现。这个异常表示在迭代集合的过程中,集合的结构发生了改变,导致迭代器无法继续正常工作。在你的引用中,checkForComodification()方法是ArrayList类中用于检测并抛出ConcurrentModificationException异常的方法。该方法会比较modCount和expectedModCount两个计数器,如果它们不相等,就会抛出ConcurrentModificationException异常。 具体地说,当一个集合在被迭代,如果在迭代过程中对集合进行了结构性修改(例如添加或删除元素),就会导致modCount和expectedModCount不相等,从而触发ConcurrentModificationException异常的抛出。 为了解决这个问题,一种常见的方法是使用Iterator迭代器的remove()方法而不是集合本身的删除方法来进行元素的删除操作。这是因为Iterator迭代器的remove()方法可以正确地更新modCount和expectedModCount计数器,从而避免了ConcurrentModificationException异常的出现。 另外,如果需要在遍历集合对其进行修改,可以考虑使用并发集合类(例如ConcurrentHashMap或CopyOnWriteArrayList),它们提供了在并发情况下安全操作集合的功能。 总之,ConcurrentModificationException异常表示在迭代集合,集合的结构发生了改变,建议使用迭代器的remove()方法进行元素的删除操作,或者考虑使用并发集合类来避免此类异常的出现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [ConcurrentModificationException异常原因以及解决方法](https://blog.csdn.net/qq_40130763/article/details/81947158)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [Java ConcurrentModificationException异常原因和解决方法](https://blog.csdn.net/weixin_40807247/article/details/88413347)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值