您的位置:首页 > 编程语言 > Java开发

java.util.ConcurrentModificationException原因

2016-10-12 20:12 357 查看
用iterator遍历集合时要注意的地方:不可以对iterator相关的地方做添加或删除操作。

下面用List为例来说明为什么会报 ConcurrentModificationException  这个异常,其它集合类似可以自己思考。

 

public static void main(String[] args){

  List set = new ArrayList();

  set.add("a10001");

  set.add("a10002");

  set.add("a10003");

  set.add("a10004");

  set.add("a10005");

  set.add("a10006");

  set.add("a10007");

  

  List del = new ArrayList();

  del.add("a10003");

  del.add("a10004");

  del.add("a10005");

  

  for(String str : set)

  {

   if(del.contains(str))

   {

    set.remove(str);

   }

  }

 }

 

运行这段代码的结果

 

Exception in thread "main" java.util.ConcurrentModificationException

 at java.util.AbstractList$Itr.checkForComodification(Unknown Source)

 at java.util.AbstractList$Itr.next(Unknown Source)

 at com.debug.Debug.main(Debug.java:28)

 

大家都知道for(String str : set) 这句话实际上是用到了集合的iterator() 方法

在iterator的时候是产生了一个List的内部类Itr 

JDK源码

public Iterator iterator() {

   return new Itr();

}

在new Itr()时有一个关键性的操作 

 int expectedModCount = modCount;

 

再回头看一下List 的 remove方法

 public boolean remove(Object o) {

 if (o == null) {

            for (int index = 0; index < size; index++)

  if (elementData[index] == null) {

      fastRemove(index);

      return true;

  }

 } else {

     for (int index = 0; index < size; index++)

  if (o.equals(elementData[index])) {

      fastRemove(index);

      return true;

  }

        }

 return false;

    }

 

private void fastRemove(int index) {

        modCount++;

        int numMoved = size - index - 1;

        if (numMoved > 0)

            System.arraycopy(elementData, index+1, elementData, index,

                             numMoved);

        elementData[--size] = null; // Let gc do its work

    }

 

再看一下 iterator.next()操作

public E next() {

            checkForComodification();

     try {

  E next = get(cursor);

  lastRet = cursor++;

  return next;

     } catch (IndexOutOfBoundsException e) {

  checkForComodification();

  throw new NoSuchElementException();

     }

 }

 

final void checkForComodification() {

     if (modCount != expectedModCount)

  throw new ConcurrentModificationException();

 }

 

相信看到这儿大家已经应该明白了为什么会出现在这个异常了。

总结:

  iterator 时 将expectedModCount = modCount 在remove()时 modCount++ 在next()时

 if (modCount != expectedModCount)

  throw new ConcurrentModificationException();

 

一旦删除或添加元素后 modCount ,expectedModCount 这两个值就会不一致 当next时就会报ConcurrentModificationException 

 

了解了原由,解决方案就很简单了 在遍历时用一个集合存放要删除的对象 在遍历完后 调用removeAll(Collection
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: