List删除元素报Exception in thread "main" java.util.ConcurrentModificationException异常,或数据删除不完整

先定义测试list

public static List<String> list = new ArrayList<String>();
	static{		
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("d");
		list.add("c");
		
		list.add("c");
		list.add("a");
		list.add("c");
		list.add("a");
		list.add("c");
	}

这里我主要用到三种方法:

1、Iterator迭代删除(建议使用)

public static List removeIterator(){
		Iterator<String> it = list.iterator();
		while(it.hasNext()){	
			String t = it.next();	
			if(t.equals("c")){
				//list.remove(t);//用list移除会报ConcurrentModificationException异常
				it.remove();
			}
		}
		return list;
	}

用iterator迭代基本都能删除,但是用list.remove()删除的话会报ConcurrentModificationException异常,可以debug进去看下异常:

final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

expectedModCount:表示对ArrayList修改次数的期望值,它的初始值为modCount。
modCount :AbstractList类中的一个成员变量,list里add、remove等操作都会使modCount++。

但在多线程下时用iterator.remove()也会报ConcurrentModificationException异常,并不全在于ArrayList是非线程安全的,换成线程安全Vector也同样会报ConcurrentModificationException异常

原因在于,虽然Vector的方法采用了synchronized进行了同步,但是由于Vector是继承的AbstarctList,因此通过Iterator来访问容器的话,事实上是不需要获取锁就可以访问。那么显然,由于使用iterator对容器进行访问不需要获取锁,在多线程中就会造成当一个线程删除了元素,由于modCount是AbstarctList的成员变量,因此可能会导致在其他线程中modCount和expectedModCount值不等。

解决办法:

1)在使用iterator迭代的时候使用synchronized或者Lock进行同步;

  2)使用并发容器CopyOnWriteArrayList代替ArrayList和Vector。

参考:http://www.jianshu.com/p/02a08c6c21ed





2、基本下标for循环

	public static List removeFor(){
		for(int i=0;i<list.size();i++){
			if("c".equals(list.get(i))){//删除为c的元素	
				list.remove(i);	
				System.out.println(list.size());//会根据remove减少,数组元素往前移,后面的会用null填补
 			}}
		System.out.println(list.toString());//输出结果:[a, b, d, c, a, a]   但是还有一个c元素并没有删除
		return list;
		}

因为下标4和5里的元素都为c,下标为4的删了,下标为5的元素移至下标为4中,但迭代值i会一直累加,所以并不会再遍历到这个内容为c的元素中,
如果要删除的元素不相邻的话是可以实现要求的。





3、增强for循环

3.1用list.remove()后还继续循环依然会报ConcurrentModificationException异常

public static List removeForeach(){
		for(String s:list){
			if("c".equals(s)){
				list.remove(s);
			}
		}
		return list;
	}

3.2但是remove()后跳出循环就不会报异常
public static List removeForeach(){
		for(String s:list){
			if("c".equals(s)){
				list.remove(s);
				break;//不跳出循环,会报ConcurrentModificationException异常
			}
		}
		return list;
	}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值