不要在 foreach 循環(huán)里進行元素的 remove/add 操作。remove 元素請使用 Iterator 方式,如果并發(fā)操作,需要對 Iterator 對象加鎖。
正例: Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String item = iterator.next();
if (刪除元素的條件) {
iterator.remove();
}
}
反例: List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
for (String item : list) {
if ("1".equals(item)) {
list.remove(item);
}
}
說明:以上代碼的執(zhí)行結(jié)果肯定會出乎大家的意料,那么試一下把“1”換成“2”,會是同樣的 結(jié)果嗎?
根本原因在于expectedModCount與modCount他們的不相等,由于執(zhí)行了ArrayList中的remove(),modCount在每一次循環(huán)值會發(fā)生改變,而expectedModCount并沒有發(fā)生,在執(zhí)行checkForComodification()方法就會拋出異常。
如下代碼:
編譯器編譯后的代碼如下:
}
首先大家應(yīng)該了解,對集合做remove,and等操作會觸修改次數(shù)(modCount)的增加。
以下是集合實現(xiàn)的Iterator.hasNext()方法
cursor:下一個元素的索引位置(調(diào)用Interator.next()是會觸發(fā)cursor+1)
size:集合長度
總結(jié):如果我們我們用foreach刪除的元素剛好是最后一個,刪除完成前cursor剛好等于size的大小。但是,刪除完成后size的數(shù)量減1,但是cursor并沒有變化。導致下一次循環(huán)不相等繼續(xù)向下執(zhí)行,導致檢查數(shù)組不通過,拋出java.util.ConcurrentModificationException
為什么使用下面的方法就不會出現(xiàn)這種情況:
請看箭頭所指處:
foreach是直接調(diào)用集合的刪除方法,而上面是調(diào)用iterator的刪除方法:
相信大家一看便知!
1.首先檢查集合
2.刪除元素
3.cursor重新賦值
4.檢查集合參數(shù)重新賦值