当do列表、集合等在Java中抛出Java. util. concurrentmodificationexception



下面的代码使用一个简单的列表,并通过foreach循环和while循环显示列表中包含的元素。

final public class Main
{
    public static void main(String... args)
    {           
        List<String>list=new ArrayList<String>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        for(Object o:list)
        {
            System.out.printf("n"+o);
        }
        Iterator<String>listIterator=list.iterator();
        //list.add("E");   If uncommented, throws an exception.
        //list.add("F");
        while(listIterator.hasNext())
        {
            System.out.printf("n"+listIterator.next());
        }
    }
}

当while循环上面被注释的两行没有被注释时,它会抛出异常java.util.ConcurrentModificationException。如果这些注释行位于Iterator<String>listIterator=list.iterator();行之上,则运行良好。在处理 ejb 中的实体时,这种异常非常常见。为什么会发生这种情况?怎样才能避免呢?

http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html

由该类的iterator和listtiterator方法返回的迭代器是快速失败的:如果在迭代器创建后的任何时间,以除通过迭代器自己的remove或add方法之外的任何方式修改列表,迭代器将抛出ConcurrentModificationException。

而不是使用:

Iterator<String>listIterator=list.iterator();

使用:

ListIterator<String> listIterator = list.listIterator();

这个迭代器提供了一个add()方法供您使用。注意在JavaDoc中它是如何工作的,尽管它可能没有提供您所需要的-它不会添加到列表的末尾,而是添加相对于ListIterator位置的位置。

每个集合维护一个名为modCount的变量。这个变量跟踪集合被修改的次数。从AbstractList

找到下面mdcount的javadoc
/**
* The number of times this list has been <i>structurally modified</i>.
* Structural modifications are those that change the size of the
 * list, or otherwise perturb it in such a fashion that iterations in
 * progress may yield incorrect results.
 *
 * <p>This field is used by the iterator and list iterator implementation
 * returned by the {@code iterator} and {@code listIterator} methods.
 * If the value of this field changes unexpectedly, the iterator (or list
 * iterator) will throw a {@code ConcurrentModificationException} in
 * response to the {@code next}, {@code remove}, {@code previous},
 * {@code set} or {@code add} operations.  This provides
 * <i>fail-fast</i> behavior, rather than non-deterministic behavior in
 * the face of concurrent modification during iteration.
 *
 * <p><b>Use of this field by subclasses is optional.</b> If a subclass
 * wishes to provide fail-fast iterators (and list iterators), then it
 * merely has to increment this field in its {@code add(int, E)} and
 * {@code remove(int)} methods (and any other methods that it overrides
 * that result in structural modifications to the list).  A single call to
 * {@code add(int, E)} or {@code remove(int)} must add no more than
 * one to this field, or the iterators (and list iterators) will throw
 * bogus {@code ConcurrentModificationExceptions}.  If an implementation
 * does not wish to provide fail-fast iterators, this field may be
 * ignored.
 */
protected transient int modCount = 0;

创建迭代器时,会保留modCount的本地副本,并在返回新对象之前进行检查。如果发生了更改,则抛出并发修改异常。

可以通过在迭代集合时不对其进行任何操作来避免异常。只允许删除,并且应该通过迭代器路由,即iterator #remove

相关内容

最新更新