java.util.ConcurrentModificationException的解決辦法
大家應該都知道, 在java中, 在對一些集合迭代的過程中對集合進行一些修改的操作, 比如說add,remove之類的操作, 搞不好就會拋ConcurrentModificationException,
前幾天在專案中,終於碰到了這個異常。
在單執行緒操作的情況下,在DAO層查詢到資料集合後,返回到service層做業務處理,要求:遍歷資料集合,判斷不符合條件的元素,做刪除操作。
在用foreach和 Iterator 都會發生java.util.ConcurrentModificationException。
看一下JavaDoc對java.util.ConcurrentModificationException異常的描述: 當方法檢測到物件的併發修改,但不允許這種修改時,丟擲此異常。
檢視原始碼後終於發現了原因是因為:
迭代器的modCount和expectedModCount的值不一致。
單執行緒中該異常出現的原因是:對一個集合遍歷的同時,有對該集合進行了增刪的操作。導致AbstarctList的modCount和expectedModCount的值不一致。
而我們要做的就是將需要操作的元素放到中間元素中,並記錄操作標誌位。在遍歷結束後進行增刪操作。
或自定義迭代器複寫其中的相關操作,在操作結束後新增expectedModCount = modCount;
多執行緒中更容易出現該異常,當你在一個執行緒中對一資料集合進行遍歷,正趕上另外一個執行緒對該資料集合進行增刪操作。
解決方案: 1)在使用iterator迭代的時候使用synchronized或者Lock進行同步;
2)使用併發容器CopyOnWriteArrayList代替ArrayList和Vector。
以下是Demo:
推薦大家
1、使用for迴圈進行遍歷集合,在for迴圈中做增刪操作。
2、用Iterator遍歷,使用iterator.remove().
package com.utils; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * @Author Libin * @Date Create in 16:02 2018/7/7 * @Modified By: */ public class Test { // 出現java.util.ConcurrentModificationException public List<String> m1(List<String> list) { for (String temp : list) { if ("3".equals(temp)) { list.remove(temp); } } return list; } public List<String> m2(List<String> list) { Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String temp = iterator.next(); if ("2".equals(temp)) { //list.remove(temp);// 出現java.util.ConcurrentModificationException iterator.remove();// 推薦使用 } } return list; } //successful! public List<String> m3(List<String> list) { for (int i = 0; i < list.size(); i++) { if ("2".equals(list.get(i))) { list.remove(i); } } return list; } public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3"); Test test = new Test(); List<String> listTemp = test.m2(list); System.out.println(listTemp.toString()); } }
List<Map>,遍歷,刪除資料也會報這個錯。