我們知道,使用疊代器周遊集合時,如果進行增删等操作,會抛出一個異常:ConcurrentModificationException并發修改異常,那麼為什麼會這樣呢?一起來研究研究
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL5IDN3IDN1ETM2AjMxgTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
如下,疊代時對集合coll進行删除操作,異常抛出
Iterator<Integer> it = coll.iterator();
while (it.hasNext()) {
int s = it.next();
coll.remove(s);//執行該操作上面的next()會抛出ConcurrentModificationException并發修改異常
System.out.println(s);
}
我們尋找控制台的資訊進入java.util.ArrayList$Itr.next(ArrayList.java:893)
發現在next方法中,有一個checkForComodification();方法,我們點進去檢視裡面都做了些什麼。
是不是很熟悉,在if判斷中抛出了這個并發修改異常,那你可能會好奇了,這個modCount和expectedModCount又是什麼東西呢?
字面意思我們先大概了解一下,mod,是modification的簡寫,修改的意思,expected:期望的,這時我們可能就會想到:噢,修改值和期望值
也就是說在疊代時,調用next方法,會調用checkForComodificatio()進行判斷,如果修改值和期望值不一緻,就抛出并發修改的異常。
我們繼續Ctrl點modCount找到它的位置,發現在AbstractList中628行定義它,初始化為0
再看expectedModCount,建立時會把modCount的值指派給它
而這兩個變量,modCount是在集合中,expectedModCount在接口中,換句話說:建立集合時會定義變量modCount,預設為0,建立疊代器時将定義expectedModCount并将modCount目前的值指派給它
我們繼續往下看,诶?
當我們調用集合的add方法時,modCount會自增,同理,調用remove方法時,也會自增(其他一些方法同理)
到這裡,我們舉一個簡單的例子來說明一下整個流程:
1.現在我建立一個ArrayList list,此時modCount為0,然後我進行4次添加操作,list.add(1),此時modCount的值為4
2.然後我建立疊代器,Iterator it = list.iterator();
此時會将modCount的值指派給expectedModCount****,expectedModCount現在也為4
3.緊接着我使用while循環來開始周遊list
while (it.hasNext()) {
int s = it.next();
list.remove(s);
System.out.println(s);
}
4.周遊時抛出了異常,這裡調用remove(s)時,modCount++,由4變成了5,上面我們講過,next方法中會調用checkForComodificatio方法判斷modCount和expectedModCount的值是否相等,不相等就會抛出異常,此時modCount為5,expectedModCount為4,下次循環到next方法,異常就抛出了
那該如何解決呢?我們直接上答案,使用ListIterator lit = list.listIterator();建立疊代器,用lit的add或remove來進行增删,你可能會想wtf?為毛這個就可行了!
别急,我們再一起到源碼中找答案
是不是瞬間就明白了,這裡的add方法中加上了一個同步操作,讓modCount和expectedModCount始終保持一緻,所有就不會抛出該異常了。
over
樓主是一隻萌新,如有錯誤之處還望大家指正