增強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