JAVA集合中删除元素时的java.util.ConcurrentModificationException

在JAVA的集合(LIST,SET)中通过iterator.hasNext() 或者iterator.next()遍历集合中的数据时,如果这时候add或者remove集合中的元素,会发生ConcurrentModificationException异常.

本文简单说明一下这种现象和解决方法.

如下面的代码,不管是remove还是add都会发生ConcurrentModificationException异常.

    public static void testWrongAccess2() {
        Collection<String> myCollection = new ArrayList<String>(10);
        myCollection.add("1");
        myCollection.add("2");
        myCollection.add("3");
        myCollection.add("4");
        Iterator itr = myCollection.iterator(); 
        while (itr.hasNext()) {
            String myObject = (String) itr.next();
            System.out.println(myObject);            
            if ("2".equals(myObject)) {
                myCollection.remove(myObject); // cause ConcurrentModificationException
                //myCollection.add("4"); // cause ConcurrentModificationException
            }
        }
    }

//1.5之后的写法也是会有异常的
        for (String myObject: myCollection) {           
            System.out.println(myObject);           
            if ("2".equals(myObject)) {
                myCollection.remove(myObject);
            }
        } 
关于remove的解决办法是:利用iterator的remove方法.

	public static void testRightAccess() {
		Collection<String> myCollection = new ArrayList<String>(10);
		myCollection.add("1");
		myCollection.add("2");
		myCollection.add("3");
		myCollection.add("4");
		Iterator itr = myCollection.iterator(); 
		while (itr.hasNext()) {
			String myObject = (String) itr.next();
			System.out.println(myObject);
			
			if ("2".equals(myObject)) {
				itr.remove();
			}
		}
	}
对于在集合满足某种条件的情况下add元素的解决:先将要add的元素放在另外一个集合里,在判断遍历完成后在加入.
	public static void testRightAccess2() {
		Collection<String> myCollection = new ArrayList<String>(10);
		myCollection.add("1");
		myCollection.add("2");
		myCollection.add("3");
		myCollection.add("4");
		
		Collection<String> tempCollection = new ArrayList<String>(10);
		
		Iterator itr = myCollection.iterator(); 
		while (itr.hasNext()) {
			String myObject = (String) itr.next();
			
			if ("1".equals(myObject)) {
				tempCollection.add("1 Exists");
			}
			
			if ("2".equals(myObject)) {
				tempCollection.add("2 Exists");
			}
			
		}
		
		myCollection.addAll(tempCollection);

	}
这里碰到一个有趣的现象:下面的代码没有发生ConcurrentModificationException,在一个只有3个元素的集合中,remove第二个元素,没有ConcurrentModificationException发生而且最后集合里只有1和3,remove 1 和 3 都会有异常,add元素也会有异常,难道是JDK的bug??总之,在remove元素的时候应该用iterator的remove方法.
	public static void testWrongAccess1() {
		Collection<String> myCollection = new ArrayList<String>(10);
		myCollection.add("1");
		myCollection.add("2");
		myCollection.add("3");
		
		Iterator itr = myCollection.iterator(); 
		while (itr.hasNext()) {
			String myObject = (String) itr.next();
			System.out.println(myObject);
			
			if ("2".equals(myObject)) {							
				myCollection.remove(myObject); // doesn't cause ConcurrentModificationException
				//myCollection.add("4"); // cause ConcurrentModificationException
			}
		}
	}
如果想在读取的同时进行修改,可以用CopyOnWriteArrayList或者CopyOnWriteArraySet
public class CopyOnWriteDemo {
	public static void main(String args[]) {
		String[] ss = { "aa", "bb", "cc" };
		List list1 = new CopyOnWriteArrayList(Arrays.asList(ss));
		List list2 = new ArrayList(Arrays.asList(ss));
		Iterator itor1 = list1.iterator();
		Iterator itor2 = list2.iterator();
		list1.add("New");
		list2.add("New");
		try {
			printAll(itor1);//不会异常
		} catch (ConcurrentModificationException e) {
			System.err.println("Shouldn't get here");
			e.printStackTrace();
		}
		
		try {
			printAll(itor2);//ConcurrentModificationException 异常
		} catch (ConcurrentModificationException e) {
			System.err.println("Will get ConcurrentModificationException");
			e.printStackTrace();
		}
		//这里会把new打印出来
		Iterator itor3 = list1.iterator();
		try {
			printAll(itor3);
		} catch (ConcurrentModificationException e) {
			System.err.println("Will get ConcurrentModificationException");
			e.printStackTrace();
		}		
	}
	
	private static void printAll(Iterator itor) {
		while (itor.hasNext()) {
			System.out.println(itor.next());
		}
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值