迭代(遍歷)時候不可以使用集合的remove和add方法,但可使用Java迭代器的remove和add方法


不要在 foreach 循環里進行元素的 remove/add 操作。remove 元素請使用 Iterator 方式。 

反例:

public class ForeachTest {
    private List<String> list = new ArrayList<String>();

    @Test
    public void forTest() {
        list.add("1");
        list.add("2");
        for(String temp : list) {
            if("1".equals(temp)) {
                list.remove(temp);
            }
        }
        for(String temp : list) {
            System.out.println(temp + " ");
        }
    }
}

結果

如果將1換成2,結果就出錯了

產生Concurrent Modification Exception原因是:當list.remove(Object o)方法之后,modCount和expectedModCount不相等了,然后當代碼執行到next()方法時,判斷了checkForComodification(),發現兩個數值不等,就拋出該Exception;add(Object o)方法也是一樣原因;

另外,Iterator是工作在一個獨立的線程中,並且擁有一個mutex鎖, Iterator 被創建之后會建立一個指向原來對象的單鏈索引表,當原來的list對象數量發生變化時,這個索引表的內容不會同步改變,所以當索引指針往后移動的時候就找不到要迭代的對象,所以按照 fail-fast 原則 Iterator 會馬上拋出 java.util.ConcurrentModificationException 異常。 所以 Iterator 在工作的時候是不允許被迭代的對象被改變的。

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

正例:

public class ForeachTest {
    private List<String> list = new ArrayList<String>();

    @Test
    public void forTest2() {
        list.add("1");
        list.add("2");
        Iterator<String> it = list.iterator();
        while(it.hasNext()) {
            String temp = it.next();
            if("2".equals(temp)) {
                it.remove();
            }
        }
        for(String temp : list) {
            System.out.println(temp + " ");
        }
    }
}

結果很完美,

如果並發操作,需要對 Iterator 對象加鎖。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM