java – ArrayList的特殊行为remove() – 为什么?

当我们删除-1并清空ArrayList时,它会抛出ConcurrentModificationException,当我们从同一个空ArrayList中删除0时,它会抛出NoSuchElementException.

请找到以下代码

public class Test {
    public static void main(String[] argv) {

        ArrayList<Integer> list = new ArrayList<Integer>();
        Iterator<Integer> it = list.iterator();
        try {
            list.remove(-1);
        } catch (indexoutofboundsexception e) {

        }
        try {
            it.next();// Throwing ConcurrentModificationException
        } catch (ConcurrentModificationException e) {
            System.err.println("ConcurrentModificationException 1");
        } catch (NoSuchElementException e) {
            System.err.println("NoSuchElementException 1 ");
        }

        list = new ArrayList<Integer>();
        it = list.iterator();
        try {
            list.remove(0);
        } catch (indexoutofboundsexception e) {
        }
        try {
            it.next();// Throwing NoSuchElementException
        } catch (NoSuchElementException e) {
            System.err.println("NoSuchElementException 2");
        } catch (ConcurrentModificationException e) {
            System.err.println("ConcurrentModificationException 2 ");
        }

    }
}

从我的理解NoSuchElementException是好的,但为什么抛出ConcurrentModificationException?

解决方法

如果检查ArrayList的代码.首先执行范围检查,然后添加修改计数.

rangeCheck(index);
modCount++;

在范围检查方法中,范围检查仅适用于正数.

if (index >= size)
     throw new indexoutofboundsexception(outOfBoundsMsg(index));

因此remove(0)不会添加mod计数,但remove(-1)会添加. modCount导致迭代器抛出ConcurrentModificationException.

相关文章

Java中的String是不可变对象 在面向对象及函数编程语言中,不...
String, StringBuffer 和 StringBuilder 可变性 String不可变...
序列化:把对象转换为字节序列的过程称为对象的序列化. 反序...
先说结论,是对象!可以继续往下看 数组是不是对象 什么是对...
为什么浮点数 float 或 double 运算的时候会有精度丢失的风险...
面试题引入 这里引申出一个经典问题,看下面代码 Integer a ...