java.util.ConcurrentModificationException 异常
这篇文章主要分析如何解决 ArrayList 中发生的 java.util.ConcurrentModificationException异常。
异常信息一般像这样:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
...
...
还原问题
你可能想要遍历一个 ArrayList,并在某些条件下删除一些元素。例如,以下代码看起来很合理:
import java.util.ArrayList;
import java.util.List;
public class AddRemoveListElement {
public static void main(String args[]) {
List<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
for (String s : list) {
if (s.equals("B")) {
list.remove(s);
}
}
}
}
输出结果:

解决方法 1
Iterator 可以用来解决这个问题。 Iterators 允许调用者在迭代期间从底层集合中删除元素。
Iterator<String> iter = list.iterator();
while(iter.hasNext()){
String str = iter.next();
if( str.equals("B") )
{
iter.remove();
}
}
解决方法 2
用 CopyOnWriteArrayList 代替 ArrayList 可以解决这个问题。CopyOnWriteArrayList 是 ArrayList 的一个线程安全的变体,它通过创建底层数组的新副本来实现所有的变更操作(如添加,设置等)。
public static void main(String args[]) {
List<String> list = new CopyOnWriteArrayList<String>();
list.add("A");
list.add("B");
for (String s : list) {
if (s.equals("B")) {
list.remove(s);
}
}
}
其他集合类型会发生类似的异常吗?
public static void main(String args[]) {
Set<String> set = new HashSet<String>();
set.add("A");
set.add("B");
for (String s : set) {
if (s.equals("B")) {
set.remove(s);
}
}
}
public static void main(String args[]) {
LinkedList<String> llist = new LinkedList<String>();
llist.add("A");
llist.add("B");
for (String s : llist) {
if (s.equals("B")) {
llist.remove(s);
}
}
}
上面的代码不会发生任何异常,因为它们不使用数组作为底层数据结构。