java java.util.ConcurrentModificationException 原因以及解决方案

原文:http://blog.csdn.net/traceofsun/article/details/5820925

用iterator遍历集合时要注意的地方:不可以对iterator相关的地方做添加或删除操作。

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

 

[cpp]  view plain copy
  1. public static void main(String[] args)  
  2.  {  
  3.   List<String> set = new ArrayList<String>();  
  4.   set.add("a10001");  
  5.   set.add("a10002");  
  6.   set.add("a10003");  
  7.   set.add("a10004");  
  8.   set.add("a10005");  
  9.   set.add("a10006");  
  10.   set.add("a10007");  
  11.     
  12.   List<String> del = new ArrayList<String>();  
  13.   del.add("a10003");  
  14.   del.add("a10004");  
  15.   del.add("a10005");  
  16.     
  17.   for(String str : set)  
  18.   {  
  19.    if(del.contains(str))  
  20.    {  
  21.     set.remove(str);  
  22.    }  
  23.   }  
  24.  }  

运行这段代码的结果

[java]  view plain copy
  1. Exception in thread "main" java.util.ConcurrentModificationException  
  2.  at java.util.AbstractList$Itr.checkForComodification(Unknown Source)  
  3.  at java.util.AbstractList$Itr.next(Unknown Source)  
  4.  at com.debug.Debug.main(Debug.java:28)  

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

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

JDK源码

public Iterator<E> iterator() {
   return new Itr();
}

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

/**
  * The modCount value that the iterator believes that the backing
  * List should have.  If this expectation is violated, the iterator
  * has detected concurrent modification.
  */
 int expectedModCount = modCount;

 

再回头看一下List 的 remove方法

[java]  view plain copy
  1.  public boolean remove(Object o) {  
  2.  if (o == null) {  
  3.             for (int index = 0; index < size; index++)  
  4.   if (elementData[index] == null) {  
  5.       fastRemove(index);  
  6.       return true;  
  7.   }  
  8.  } else {  
  9.      for (int index = 0; index < size; index++)  
  10.   if (o.equals(elementData[index])) {  
  11.       fastRemove(index);  
  12.       return true;  
  13.   }  
  14.         }  
  15.  return false;  
  16.     }  
  17.    
  18. private void fastRemove(int index) {  
  19.         modCount++;  
  20.         int numMoved = size - index - 1;  
  21.         if (numMoved > 0)  
  22.             System.arraycopy(elementData, index+1, elementData, index,  
  23.                              numMoved);  
  24.         elementData[--size] = null// Let gc do its work  
  25.     }  
  26.    


再看一下 iterator.next()操作

[java]  view plain copy
  1. public E next() {  
  2.             checkForComodification();  
  3.      try {  
  4.   E next = get(cursor);  
  5.   lastRet = cursor++;  
  6.   return next;  
  7.      } catch (IndexOutOfBoundsException e) {  
  8.   checkForComodification();  
  9.   throw new NoSuchElementException();  
  10.      }  
  11.  }  
  12.    
  13. final void checkForComodification() {  
  14.      if (modCount != expectedModCount)  
  15.   throw new ConcurrentModificationException();  
  16.  }  
  17.    

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

总结:

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

 if (modCount != expectedModCount)
  throw new ConcurrentModificationException();

 

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

 

了解了原由,解决方案就很简单了 在遍历时用一个集合存放要删除的对象 在遍历完后 调用removeAll(Collection<?> c) 就OK了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值