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了。
相關文章
相關標籤/搜索