执行ArrayList的remove(object)方法抛异常?
source link: http://www.cnblogs.com/Johnson-lin/p/13277592.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
简介
或许有很多小伙伴都尝试过如下的代码:
ArrayList<Object> list = ...; for (Object object : list) { if (条件成立) { list.remove(object); } }
然后会发现抛出 java.util.ConcurrentModificationException
异常,这是一个并发异常。那么这个到底是什么情况?首先需要介绍一下 增强for循环
增强for循环
增强for循环是Java1.5后,Collection实现了Iterator接口后出现的。增强for循环的代码如下
for (Object object : list) { // 操作 }
其实增强for循环就是使用Iterator迭代器进行迭代的,增强for循环就变成下面这样:
Iterator<Object> iterator = list.iterator(); while (iterator.hasNext()) { iterator.next(); // 操作 }
那么为什么在增强for循环中调用 list.remove(object)
会出事呢?那么咱们看看ArrayList下的 Iterator的实现类: Itr类
Itr子类
Itr子类是Iterator的实现类,属于ArrayList私有的局部内部类。我截取了Itr类的部分代码,如下:
private class Itr implements Iterator<E> { int cursor; // index of next element to return int expectedModCount = modCount; Itr() {} public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); ... } final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); } }
elementData是ArrayList存放元素的数组,上面代码没有贴出来。
size是elementData实际存放的容量大小
modCount记录elementData容量的修改次数
expectedModCount记录实例化迭代器Itr时,elementData容量的修改次数
注意!:在迭代器中,当执行 next
方法的时候,会去调用 checkForComodification
方法,判断elementData 的容量是否被修改过。
然后来看看ArrayList的remove(object)方法,截取部分代码如下:
public boolean remove(Object o) { for (int index = 0; index < size; index++) if (找到目标元素) { fastRemove(index); return true; } return false; } private void fastRemove(int index) { modCount++; // 移除操作 }
可以发现,调用remove(object)方法时调用了fastRemove方法,在fastRemove方法中执行 modCount++
!
现在把文章开头的代码拷下来,再来分析一次:
ArrayList<Object> list = ...; for (Object object : list) { if (条件成立) { list.remove(object); } }
当执行了 list.remove
时,执行 modCount++
。此时迭代器再往下进行迭代,执行了next方法,发现 modCount != expectedModCount
,那么则抛出 java.util.ConcurrentModificationException
异常。 之所以Iterator认为是一个并发异常。是因为你不在迭代器里操作,而是在迭代器外面进行remove操作呀!
难道没有其他解决方案吗?有滴。
解决方案
那么就是使用Itr的 remove方法。Itr子类重写了 remove 方法,这里部分代码:
public void remove() { ... try { ArrayList.this.remove(需要删除元素的索引); ... expectedModCount = modCount; } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } }
其实很简单,就是remove后,把 expectedModCount 同步一下 modCount 的值,这就解决了。完整代码如下:
ArrayList<Object> list = ...; Iterator<Object> iterator = list.iterator(); while (iterator.hasNext()) { iterator.next(); iterator.remove(); }
总结
本来我还不知道增强for循环是调用Iterator进行迭代的,要不是我debug了一波,我还不知道呐。还是小有收货。
个人博客网址: https://colablog.cn/
如果我的文章帮助到您,可以关注我的微信公众号,第一时间分享文章给您
Recommend
-
22
SQL Server 2017 SQLPS执行Ad-SqlAvailabilityDatabase遇到问题这个错误简直逆天,查了下该cmdlet的帮助常规参数里有Debug。执行Debug,输出如下:PS C:\Windows\system32> Add-SqlAvailabilityDatabase -InputObject $ag -Database $DatabaseList -Deb
-
8
Remove Artificial Object Graph Limit in BinaryFormatter #23971 Closed
-
10
【Linux】执行shell脚本出现异常:bad interpreter- No such file or directory如何解决 在Linux中执行.sh脚本,异常/bin/bash^M: bad interpreter: No such file or directory.
-
5
CronJob 计划任务异常不执行的问题 作者: 张志强 ...
-
5
Using the delete Keyword to Remove Object Properties May 12 ・1 min read ...
-
4
@ashykAshok KumarJavascript developerWe can use the Set object to remove the duplicates from an array. The Set object lets you store unique va...
-
2
2 Ways to Remove a Property from an Object in JavaScriptA JavaScript object is a collection of properties, where each property has a name and a value. const employee = { name: 'John Smith', position: 'Sales Ma...
-
4
We often encounter a requirement to delete specific properties from a javascript object. This article demonstrates easy ways to delete single or multiple properties from a javascript object...
-
3
New issue Remove Py2 class object inheritance #973
-
6
Java抛出异常后,后续代码是否继续执行? 作者:技术老男孩 2023-10-12 10:04:03 Java 抛出异常后,后面的语句到底是怎么执行的呢?哪些会继续执行,哪些不再执行,这是本章要探讨的问题。 Java 抛出异常...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK