解决Java ArrayList的ConcurrentModificationException问题

工作中应用ArrayList的场景很多,其中遍历ArrayList的过程中删除其中元素的情况相信也不少,而且相信很多人都会遇到ConcurrentModificationException异常。我们来研究一下为何会抛这个异常,并制定解决方法。

[b]在jdk5之后有5种遍历并删除的写法:[/b]


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListRemoveTest {
public static void main(String[] args) {
ListRemoveTest test = new ListRemoveTest();

System.out.println("-1-使用jdk5.0以后的增强for循环去remove");
List<String> list = test.buildList();
try {
for (String str : list) {
list.remove(str);
}
} catch (Exception e) {
// java.util.ConcurrentModificationException
e.printStackTrace();
}

System.out.println("-2-使用Iterator的remove");
list = test.buildList();
try {
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next();
iterator.remove();
}
} catch (Exception e) {
// java.lang.IllegalStateException
e.printStackTrace();
}

System.out.println("-3-iterator遍历+list的remove");
try {
list = test.buildList();
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
String str = (String) iterator.next();
list.remove(str);
}
} catch (Exception e) {
// java.util.ConcurrentModificationException
e.printStackTrace();
}

System.out.println("-4-使用list的remove(int)方法. [由后向前删除]");
list = test.buildList();
for (int i = list.size(); i > 0; i--) {
list.remove(i - 1);
}

System.out.println("-5-使用list的remove(int)方法. [由前向后删除]");
list = test.buildList();
for (int i = 0; i < list.size(); i++) {
list.remove(0);
}
}

private List<String> buildList() {
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
return list;
}
}



[b]运行结果:[/b]

-1-使用jdk5.0以后的增强for循环去remove
java.util.ConcurrentModificationException
-2-使用Iterator的remove
-3-iterator遍历+list的remove
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:781)
at java.util.ArrayList$Itr.next(ArrayList.java:753)
at com.jdk.ListRemoveTest.main(ListRemoveTest.java:14)
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:781)
at java.util.ArrayList$Itr.next(ArrayList.java:753)
at com.jdk.ListRemoveTest.main(ListRemoveTest.java:39)
-4-使用list的remove(int)方法. [由后向前删除]
-5-使用list的remove(int)方法. [由前向后删除]


2,4,5运行正常,1,3抛出
java.util.ConcurrentModificationException


[b]原因分析:[/b]
1,3都是因为list的长度改变,Iterator执行next()方法时,调用checkForComodification()时出错,1,3是同一个问题,这两个方法remove操作都是执行的是ArrayList中的remove方法,根本原因在于expectedModCount与modCount他们的不相等,由于执行了ArrayList中的remove(),modCount在每一次循环值会发生改变,而expectedModCount并没有发生,在执行checkForComodification()方法就会抛出异常。
2之所以正确运行是因为调用了Iterator的remove方法,4,5不会执行checkForComodification()操作,所以不会出现这种异常。

[b]结论:[/b]
在执行remove()不要将ArrayList 与Iterator混合使用,单独使用Iterator以及ArrayList的删除都是OK的 :D

[b]注意事项:[/b]
在使用Iterator的时候,必须先调用next()来获取第一个元素,否则调用remove()的时候会抛IllegalStateException错误。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值