爲何不推薦在 for 循環中 remove 元素?

業務中有須要過濾的需求,踩了 foreach 的坑。原本是這樣寫的。java

user.forEach(u -> {
                ageList.forEach(a -> {
                    if (u.getId().equals(a)) {
                        user.remove(u);
                    }
                });
            });
        }
複製代碼

改進後是這樣的。ui

Iterator<SocNearbyRespDto> ui = user.iterator();
            while (ui.hasNext()){
                SocNearbyRespDto u = ui.next();
                ageList.forEach(a->{
                    if (!u.getId().equals(a)){
                        ui.remove();
                    }
                });
            }
        }
複製代碼

Java 中一般有三種循環。spa

for (int i = 0; i < list.size(); i++) {
    System.out.print(list.get(i) + ",");
}

Iterator iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.print(iterator.next() + ",");
}

for (Integer i : list) {
    System.out.print(i + ",");
}
複製代碼

list.foreach 跟代碼中第三種加強型 for 循環同樣,反編譯的內容是線程

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

這樣在 for 循環中調用會出現 ConcurrentModificationException 異常。指針

Iterator是工做在一個獨立的線程中,而且擁有一個 mutex 鎖。 Iterator被建立以後會創建一個指向原來對象的單鏈索引表,當原來的對象數量發生變化時,這個索引表的內容不會同步改變,因此當索引指針日後移動的時候就找不到要迭代的對象,因此按照 fail-fast 原則 Iterator 會立刻拋出java.util.ConcurrentModificationException異常。code

因此改爲用 Iterator.remove() 就行了。對象

相關文章
相關標籤/搜索