遍歷集合的同時對集合進行操作

本人新手,之前遇到了一個遍歷集合的同時過濾部分不需要的元素,直接遍歷的使用list.remove(obj)的時候遇到了ConcurrentModificationException異常信息,一番查找後知道了,需要用Iterator操作才行:

 @Test
    public void  testUpdateListWhenErgodic(){
        List<String>  list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        for(Iterator iterator = list.iterator(); iterator.hasNext(); ){
            String  str =iterator.next().toString();
                iterator.remove();
        }
    }


以下內容轉載:

原因: jdk5.0以上的for-each也是利用內部的iterator來遍歷集合的(跟以前的iterator一樣)獲得的Iterator是一個內部類產生的迭代器這個迭代器在調用next方法時會檢查列表是否被修改過如果被修改過就會拋出ConcurrentModificationException異常。進一步說當使用 fail-fast iterator 對Collection 或 Map 進行迭代操作過程中嘗試直接修改 Collection / Map 的內容時即使是在單線程下運xi,java.util.ConcurrentModificationException 異常也將被拋出。Iterator 是工作在一個獨立的線程中並且擁有一個 mutex 鎖。 Iterator 被創建之後會建立一個指向原來對象的單鏈索引表當原來的對象數量發生變化時這個索引表的內容不會同步改變所以當索引指針往後移動的時候就找不到要迭代的對象所以按照 fail-fast 原則 Iterator 會馬上拋出 java.util.ConcurrentModificationException 異常。  所以 Iterator 在工作的時候是不允許被迭代的對象被改變的。但你可以使用 Iterator 本身的方法 remove() 來刪除對象,Iterator.remove() 方法會在刪除當前迭代對象的同時維護索引的一致性。

有意思的是如果你的 Collection / Map 對象實際只有一個元素的時候 ConcurrentModificationException 異常並不會被拋出。這也就是爲什麼在 javadoc 裏面指出: it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.

解決方法:在Map或者Collection的時候不要用它們的API直接修改集合的內容如果要修改可以用Iteratorremove()方法

發佈了27 篇原創文章 · 獲贊 83 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章