foreach循环删除List,报错Exception in thread "main" java.util.ConcurrentModificationException

使用for(Event e: eventList)循环删除eventList时,报错"Exception in thread "main" java.util.ConcurrentModificationException";

使用for(Event e: new ArrayList<Event>(eventList))循环删除eventList时,成功;

public class Controller {
	private List<Event> eventList = new ArrayList<Event>();
	public void addEvent(Event  c){
		eventList.add(c);
	}
	public void run(){
		while(eventList.size()>0)
			for(Event e: eventList){//ArrayList<Event>(eventList)
				if(e.ready()){
					System.out.println(e);
					e.action();
					eventList.remove(e);  //注掉该行代码无运行错误了
					//eventList.add(e);
				}
			}
	}
}

方式一:foreach迭代循环,会调用内部类iterator的next方法,和hasNext()方法,iterator初始化时会将expectedModCount 初始化为modCount;next方法会执行checkForComodification()检查;

private class Itr implements Iterator<E> {
	/**
	 * Index of element to be returned by subsequent call to next.
	 */
	int cursor = 0;

	/**
	 * Index of element returned by most recent call to next or
	 * previous.  Reset to -1 if this element is deleted by a call
	 * to remove.
	 */
	int lastRet = -1;

	/**
	 * The modCount value that the iterator believes that the backing
	 * List should have.  If this expectation is violated, the iterator
	 * has detected concurrent modification.
	 */
	int expectedModCount = modCount;
public E next() {
            checkForComodification();
	    try {
		E next = get(cursor);
		lastRet = cursor++;
		return next;
	    } catch (IndexOutOfBoundsException e) {
		checkForComodification();
		throw new NoSuchElementException();
	    }
	}
final void checkForComodification() {
	    if (modCount != expectedModCount)
		throw new ConcurrentModificationException();
	}

而在循环层面,eventList.remove(e)只会增加modCount值,不会改变expectedModCount的值,请看ArrayList.class中的remove(Object o)代码,所以下次循环判断时,next方法中checkForComodification()检查失败报错;


    public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }
   /*
     * Private remove method that skips bounds checking and does not
     * return the value removed.
     */
    private void fastRemove(int index) {
        modCount++;
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size] = null; // clear to let GC do its work
    }

方式二:每次for循环判断条件,都会动态新创建一个指向eventList的ArrayList,这样每次expectedModCount都被初始化为modCount;检查不会出问题;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值