java.util.ConcurrentModification

作者: 选一个昵称这么难 | 来源:发表于2017-09-19 18:12 被阅读276次

    1.还原事故现场

          ArrayList<Integer> list = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                list.add(i);
            }
            Iterator<Integer> iterator = list.iterator();
            ListIterator<Integer> integerListIterator = list.listIterator();
            integerListIterator.next();
            while (iterator.hasNext()){
                Integer next = iterator.next();
                if (next == 3){
                    list.remove(next);//java.util.ConcurrentModificationException
                }
                System.out.println(next);
            }
    

    2.解析
    上面简单模拟了异常出现的情况,下面看看异常出现的原因,从

    list.listIterator();
    

    入手,点进去看看这个方法的返回值

      public Iterator<E> iterator() {
            return new Itr();
        }
    

    原来就是返回的Itr这个实现了Iterator接口的类
    下面我们来看看这个类是怎么实现的,很简单(删减了和本次主题无关的东西)

    private class Itr implements Iterator<E> {
            //集合的大小
            protected int limit = ArrayList.this.size;
            int cursor;       // index of next element to return
            int lastRet = -1; // index of last element returned; -1 if no such
            int expectedModCount = modCount;
    
            public boolean hasNext() {
                return cursor < limit;
            }
    
            @SuppressWarnings("unchecked")
            public E next() {
                  //这里是报异常的地方,也就是当modCount!=expectedModCount的时候会报异常
                  //我们看到,在这个类初始化的时候expectedModCount = modCount,
                  //在使用next()或者hasNext()方法的时候没有改变expectedModCount的值
                  //也就是说modCount的值改变,造成这两个值不一样了
                  //通过查看ArrayList的增删等方法,发现没操作一次增删等方法,这个modCount就++
                  //modCount就是记录的这个集合被修改的次数
                  //因此我们就明白了为什么在使用iterator迭代的时候不能修改
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
                int i = cursor;
                if (i >= limit)
                    throw new NoSuchElementException();
                Object[] elementData = ArrayList.this.elementData;
                if (i >= elementData.length)
                    throw new ConcurrentModificationException();
                cursor = i + 1;
                return (E) elementData[lastRet = i];
            }
            //但是我还想在迭代的时候进行删除操作怎么办?
            //那么就用下面这个方法,这个方法进行删除操作仍然会保证modCount == expectedModCount
            public void remove() {
                if (lastRet < 0)
                    throw new IllegalStateException();
                if (modCount != expectedModCount)
                    throw new ConcurrentModificationException();
    
                try {
                    ArrayList.this.remove(lastRet);
                    cursor = lastRet;
                    lastRet = -1;
                    expectedModCount = modCount;
                    limit--;
                } catch (IndexOutOfBoundsException ex) {
                    throw new ConcurrentModificationException();
                }
            }
          ...
        }
    

    list除了iterator()方法还有一个list.listIterator()方法
    这个方法返回的iterator功能更强大,比如可以增加一个值,可以更新一个值等

    相关文章

      网友评论

        本文标题:java.util.ConcurrentModification

        本文链接:https://www.haomeiwen.com/subject/qokgsxtx.html