1. 程式人生 > 其它 >增強for迴圈(foreach)的坑

增強for迴圈(foreach)的坑

使用foreach時,出現了ConcurrentModificationException

然後就去搜了搜,直接看吧

這裡說是增強for迴圈的坑,其實主要是因為有些人不瞭解增強for迴圈的實現原理而可能踩入的坑。

既然增強for迴圈通過迭代器實現,那麼必然有迭代器的特性。

Java中有fail-fast機制。在使用迭代器遍歷元素的時候,在對集合進行刪除的時候一定要注意,使用不當有可能發生ConcurrentModificationException,這是一種執行時異常,編譯期並不會發生。只有在程式真正執行時才會爆發。

如以下程式碼:

for (Student stu : students) { 
 
if (stu.getId() == 2) students.remove(stu); }

會丟擲ConcurrentModificationException異常。

Iterator是工作在一個獨立的執行緒中,並且擁有一個 mutex 鎖。 Iterator被建立之後會建立一個指向原來物件的單鏈索引表,當原來的物件數量發生變化時,這個索引表的內容不會同步改變,所以當索引指標往後移動的時候就找不到要迭代的物件,所以按照 fail-fast 原則 Iterator 會馬上丟擲
java.util.ConcurrentModificationException異常。

所以 Iterator 在工作的時候是不允許被迭代的物件被改變的。

但你可以使用 Iterator 本身的方法remove()來刪除物件,Iterator.remove()方法會在刪除當前迭代物件的同時維護索引的一致性。

正確的在遍歷的同時刪除元素的姿勢:

Iterator<Student> stuIter = students.iterator(); 
while (stuIter.hasNext()) { 
 Student student = stuIter.next(); 
 if (student.getId() == 2) 
 stuIter.remove();//這裡要使用Iterator的remove方法移除當前物件,如果使用List的remove方法,則同樣會出現ConcurrentModificationException 
}

ok,然後想簡單瞭解了foreach的原理(其實還是用到了迭代器Iterator):

我們對以下程式碼進行反編譯:

for (Integer i : list) {
 System.out.println(i);
}

反編譯後:

Integer i;
for(Iterator iterator = list.iterator(); iterator.hasNext(); System.out.println(i)){
 i = (Integer)iterator.next();
}

哦,原來是這樣啊,那沒事了

文章借鑑(基本都是copy)於:https://www.jb51.net/article/138234.htm