java源码分析(12)-ConcurrentModificationException

来源:互联网 发布:人工智能计算器旧版本 编辑:程序博客网 时间:2024/05/21 23:31

ConcurrentModificationException

此异常在使用迭代器时经常出现,主要原因为迭代器迭代未完成之前,容器属性被更改。例如下面的一段程序:

public static void main(String[] args) {ArrayList<Integer> list=new ArrayList<Integer>();list.add(1);list.add(2);list.add(3);Iterator<Integer> iterator=list.iterator();while(iterator.hasNext()){Integer i=iterator.next();if(i==1){list.remove(i);}}}
如上图的代码所示,便会报ConcurrentModificationException异常,原因为在使用迭代器时,又使用了list的remove方法,使list的属性发生了变化,但却通知迭代器,迭代器在下次循环时发现容器属性发生变化而报错。下面请看源码

</pre><pre name="code" class="java">public Iterator<E> iterator() {     return new Itr();}private class Itr implements Iterator<E> {        int cursor; //迭代器next指向的下标              int lastRet = -1; //现在指向的下标        int expectedModCount = modCount;//modCount为AbstractList中定义的属性,用于记录list被更改的次数        public boolean hasNext() {            return cursor != size;        }        @SuppressWarnings("unchecked")        public E next() {            checkForComodification();//用于确认容器的属性是否发生变化(未通知迭代器的属性改变)            int i = cursor;            if (i >= size)                throw new NoSuchElementException();            Object[] elementData = ArrayList.this.elementData;            if (i >= elementData.length)                throw new ConcurrentModificationException();            cursor = i + 1;            return (E) elementData[lastRet = i];        }        public void remove() {            if (lastRet < 0)                throw new IllegalStateException();            checkForComodification();            try {                ArrayList.this.remove(lastRet);                cursor = lastRet;                lastRet = -1;                expectedModCount = modCount;//可以看到迭代器中的remove方法在移除元素后,还将修改后的modCount通知了迭代器,使迭代过程中的list属性保持一致            } catch (IndexOutOfBoundsException ex) {                throw new ConcurrentModificationException();            }        }        final void checkForComodification() {            if (modCount != expectedModCount)//判断有效性,在迭代过程中,若出现非迭代器更改list的情况,将会抛异常以此来保证list属性的一致性                throw new ConcurrentModificationException();        }    }

所以,在使用迭代器时,若需要移除数据,请使用迭代器的remove方法,程序代码改为以下即可:
         public static void main(String[] args) {ArrayList<Integer> list=new ArrayList<Integer>();list.add(1);list.add(2);list.add(3);Iterator<Integer> iterator=list.iterator();while(iterator.hasNext()){Integer i=iterator.next();if(i==1){    iterator.remove();}}}


0 0
原创粉丝点击