Java_foreach不能remove


foreach

阿里巴巴java開發手冊

【強制】不要在foreach循環里進行元素的remove/add操作。remove元素請使用Iterator方式,如果並發操作,需要對Iterator對象加鎖。

反例
 List<String> a = new ArrayList<String>(); 
 a.add("1");
 a.add("2");
 for (String temp : a) { 
    if("1".equals(temp)){
         a.remove(temp); 
     } 
 } 
 正例
 Iterator<String> it= a.iterator(); 
while(it.hasNext()){ 
    String temp = it.next(); 
    if(刪除元素的條件){ 
        it.remove(); 
    } 
}

foreach源碼

foreach遍歷集合,其實是走的Iterator,首先判斷hasNext(),如果沒有了則終止循環,否則next()獲取元素時,next()時,都要check一下集合元素個數是否變化了,如果變化了,則拋出異常。

Itr是ArrayList的內部類,實現了Iterator接口

private class Itr implements Iterator<E> {

 int cursor;       // index of next element to return
 int lastRet = -1; // index of last element returned; -1 if no such
 int expectedModCount = modCount;

 public boolean hasNext() {
            return cursor != size;//游標不等於元素個數就是還有下一個
 }

public E next() {
     checkForComodification();//check是否並發修改
      int i = cursor;
      if (i >= size)
          throw new NoSuchElementException();
      Object[] elementData = ArrayList.this.elementData;
      if (i >= elementData.length)
          throw new ConcurrentModificationException();
      cursor = i + 1;
      return (E) elementData[lastRet = i];
  }

 final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
  }
}

modCount是集合添加元素、刪除元素的次數,expectedModCount是預期的修改次數。增刪操作會使得modCount+1,不等於expetedModCount,所以拋出異常。

沒有使用list.iterator時調用的是ArrayList自己的remove,並不會同步這兩個值,導致拋出異常。調用了ArrayList.iterator之后,然后了Itr對象,此后再remove,remove方法中有讓這兩個值相等的操作。

迭代器方式移除

那為什么Iterator不會異常呢?

public void remove() {
    if (lastRet < 0)
        throw new IllegalStateException();
    checkForComodification();

    try {
        ArrayList.this.remove(lastRet);
        cursor = lastRet;
        lastRet = -1;
        expectedModCount = modCount;//這里預期的修改次數改為實際修改次數
    } catch (IndexOutOfBoundsException ex) {
        throw new ConcurrentModificationException();
    }
}

迭代器的remove方法會修改expectedModCount,從而使modCount與之相等

參考:https://blog.csdn.net/wangjun5159/article/details/61415358


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM