📜  在Java使用迭代器时出现 ConcurrentModificationException(1)

📅  最后修改于: 2023-12-03 15:37:36.419000             🧑  作者: Mango

在Java使用迭代器时出现 ConcurrentModificationException

在Java中,迭代器是一种方便和安全访问集合元素的方法。然而,在使用迭代器遍历集合时,有时会出现ConcurrentModificationException的异常,本文将介绍该异常的产生原因和解决方法。

问题描述

在使用迭代器遍历集合时,若在遍历时修改了集合的结构(比如添加或删除元素),就会导致ConcurrentModificationException异常的抛出。

例如下述代码片段(Java 8):

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
for (Integer i : list) {
    if (i == 3) {
        list.remove(i);
    }
}

执行该代码时,就会出现ConcurrentModificationException异常。

问题原因

当调用集合的iterator()方法时,在迭代器被创建时,会将集合的modCount值保存在迭代器的expectedModCount变量中。

在每次使用迭代器遍历集合时,都会比较expectedModCount与集合的modCount是否相等,如果不相等,就说明集合已经被修改,抛出ConcurrentModificationException异常。

而在上述代码中,我们在遍历时直接修改了集合,导致了异常的抛出。

解决方法
  1. 使用迭代器的remove()方法:在遍历集合时,调用迭代器的remove()方法,而不是直接调用集合的remove()方法。

    例如:

    List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
    for (Iterator<Integer> iterator = list.iterator(); iterator.hasNext();) {
        Integer i = iterator.next();
        if (i == 3) {
            iterator.remove();
        }
    }
    

    在以上代码中,我们使用了迭代器的remove()方法,而没有直接修改集合,就避免了ConcurrentModificationException异常的抛出。

  2. 将集合复制到一个临时集合中:在遍历集合时,将集合复制到一个临时的集合中进行遍历,修改集合时也只在临时集合中进行,最后再将临时集合中的元素复制回原集合中。

    例如:

    List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
    List<Integer> tempList = new ArrayList<>(list);
    for (Integer i : tempList) {
        if (i == 3) {
            list.remove(i);
        }
    }
    

    在以上代码中,我们将原集合复制到了临时集合tempList中进行遍历和修改,最后再将tempList中的元素复制回原集合list中。

以上就是在Java使用迭代器时出现ConcurrentModificationException异常的解决方法。我们应该在代码中遵守集合与迭代器的规范,以避免这一问题的发生。