使用Iterator 或for-each注意:java.util.ConcurrentModificationException Posted on 2010-03-02 12:22
Fingki.li 閱讀(1360)
評論(1) ?
編輯 ?
收藏 所屬分類:
About development
在使用Iterator處理Collection時,注意java.util.ConcurrentModificationException。
1.如果你僅僅是對collection進行遍歷查詢,那么不必擔心什么。
2.但如果你在遍歷過程中要對collection進行刪除,那么你就要注意了。
For example:
private?void?testDel()?{??
????List<String>?list?=?new?ArrayList<String>();?? ????for?(int?i?=?0;?i?<?10;?i++)?{?? ????????String?str?=?"td"?+?i;?? ????????list.add(str);?? ????}?? ?? ????for?(Iterator?it?=?list.iterator();?it.hasNext();)?{?? ????????String?str?=?(String)?it.next();?? ????????if?(str.equals("td5"))?{?? ????????????//?list.remove(str);??// 刪除方法一? ????????????it.remove();??// 刪除方法二? ????????}?? ????}?? }? 上面的代碼運行沒有問題,但如果你用“方法一”替代“方法二”,則會出現(xiàn)java.util.ConcurrentModificationException。
(用for-each遍歷也會出個類似問題)
具體原因是可以看一下
先看看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++;?//?特別注意這里,這里只增加了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?? }? 接著看。刪除后得到下一個元素的代碼,it.next():? it為AbstractList的內(nèi)部類Iterator的一個實例。
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的remove()方法的源代碼:
public?void?remove()?{?? ????if?(lastRet?==?-1)?? ????????throw?new?IllegalStateException();?? ????checkForComodification();?? ????try?{?? ????????AbstractList.this.remove(lastRet);?? ????????if?(lastRet?<?cursor)?? ????????????cursor--;?? ????????lastRet?=?-1;?? ????????expectedModCount?=?modCount;?//?設(shè)置expectedModCount?? ????}?catch?(IndexOutOfBoundsException?e)?{?? ????????throw?new?ConcurrentModificationException();?? ????}?? }?? ?? final?void?checkForComodification()?{?? ????if?(modCount?!=?expectedModCount)?? ????????throw?new?ConcurrentModificationException();?? }? 這下就明白了,list的remove方法只修改了modCount值,而iterator的remove能同步modCount和expectedModCount.
新人創(chuàng)作打卡挑戰(zhàn)賽 發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!
總結(jié)
以上是生活随笔 為你收集整理的使用Iterator 或for-each注意:java.util.ConcurrentModificationException 的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔 推薦給好友。