使用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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/299853.html
標籤:其他
下一篇:JVM學習1
