java.util.ConcurrentModificationException


[這篇博文,多虧cnblogs的管理員GG幫忙恢復,才得以重見天日,特在此拜謝!]

在使用set/map時,一個可愛的小bug:java.util.ConcurrentModificationException

 

【錯誤場景1】:set容器,邊遍歷,邊add/remove元素

Set<String> set = new HashSet<String>();
for (int i = 0; i < 10000; i++) {
    set.add(Integer.toString(i));
}
for (String str : set) { //或使用iterator來循環,JDK5.0以上,這樣的遍歷底層也都是iterator實現。
    set.add("xxx"); //報錯
//  set.remove(str); //報錯
}
 
        
【錯誤場景2】:map容器,邊遍歷,邊remove元素
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < 100; i++) {
    map.put(Integer.toString(i), Integer.toString(i));
}
for (String str : map.keySet()) {//或使用iterator來循環
    map.remove(str); //報錯
}
 
          
【錯誤場景3】list容器,邊遍歷,邊add/remove元素
List<String> list = new ArrayList<String>();
        for (int i = 0; i < 100; i++) {
            list.add(Integer.toString(i));
        }
        for (Iterator<String> it = list.iterator(); it.hasNext();) { 
            String val = it.next();
            if (val.equals("5")) {
                list.add(val); //報錯
                //     list.remove(val);   //報錯    
            }
        }
 

【錯誤原因】

  • 對於remove操作,list.remove(o)的時候,只將modCount++,而expectedCount值未變,那么迭代器在取下一個元素的時候,發現該二值不等,則拋ConcurrentModificationException異常。
  • 對於add操作,同remove

【解決辦法】

  • remove:用iterator提供的原生態remove()
  •  

     

     

     

     

     

    add:同remove就錯了,iterator沒有提供原生的add()方法。真是的,還要用新的容器暫存,然后再遍歷結束后,全部添加到原容器當中。

  • set/list:這兩類常用容器,就用上面說的方法remove(), add()就好了。

  • map:直接使用ConcurrentHashMap就ok。為什么別的容器,不也實現個concurrent版本直接用。。?庫里不搞,自己搞。

【正確使用案例】

for (Iterator<String> it = list.iterator(); it.hasNext();) {
    String val = it.next();
    if (val.equals("5")) {
        it.remove(); 
    }
}
List<String> newList = new ArrayList<String>(); 
for (Iterator<String> it = list.iterator(); it.hasNext();) {
    String val = it.next();
    if (val.equals("5")) {
        newList.add(val);
    }
}
list.addAll(newList);


免責聲明!

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



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