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 可以解决这个问题。CopyOnWriteArrayListArrayList 的一个线程安全的变体,它通过创建底层数组的新副本来实现所有的变更操作(如添加,设置等)。

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);
        }
    }
}

上面的代码不会发生任何异常,因为它们不使用数组作为底层数据结构。

results matching ""

    No results matching ""