java.util.ConcurrentModificationException原因

用iterator遍历集合时要注意的地方:不可以对iterator相关的地方做添加或删除操作。  
  
下面用List为例来说明为什么会报 ConcurrentModificationException  这个异常,其它集合类似可以自己思考。  
  
   
  
public static void main(String[] args){  
  List<String> set = new ArrayList<String>();  
  set.add("a10001");  
  set.add("a10002");  
  set.add("a10003");  
  set.add("a10004");  
  set.add("a10005");  
  set.add("a10006");  
  set.add("a10007");  
    
  List<String> del = new ArrayList<String>();  
  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<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方法  
  
 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<?> c) 就OK了。  

 

转载于:https://my.oschina.net/u/2450896/blog/683904

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值