java list只有两个元素时,循环删除(remove)元素不会报ConcurrentModificationException异常

我们都知道,java中的ArrayList在使用增强for循环或iterator循环中调用list本身的remove方法删除元素时会报ConcurrentModificationException异常,通过iterator的remove方法来删除就不会报异常了。当然增强for循环只是个语法糖,本质还是用的iterator。今天想试验一下这个异常,于是写了如下代码。

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    list.add("abc");
    list.add("123");
    System.out.println(list);
    Iterator<String> iterator = list.iterator();
    while (iterator.hasNext()) {
        String next = iterator.next();
        list.remove(next);
    }
    System.out.println(list);
}

结果输出如下,并没有报错,这就奇怪了,不是说在循环中调用list的remove方法会异常吗,为什么没有呢?如果我把list的元素个数改成3个,就会报异常了,原因的话看一下源码就知道了。

导致这个现象的原因和hasNext()方法有关系,看一下hasNext()源码,cursor是当前遍历到的元素下标,每当我们调用iterator.next()方法时,这个cursor就会加1,当cursor的大小和list中的size一样时,说明遍历到数组尾部了,就没有元素了,hasNext()就会返回false。

接下来分析我们上面的程序,循环开始前,cursor=0,不等于size的大小2,进入循环,调用next()方法,调用next()方法时会调用checkForComodification(),也就是判断一下在循环过程中list是否被改变过,由于我们第一次循环,还没有对list做过改变,所以next可以正常返回。返回下标0处的"abc",此时cursor被置为了1,再调用remove方法,此时list中就只有“123”这个元素了,size为1。

再次循环,由于此时cursor为1,我们remove了一个元素后,list的size也变为了1,所以hasNext()判断为false了,就跳出循环了,然后程序结束。

也就是说,虽然我们list中有两个元素,但是实际上for循环只进行了一次,只把“abc”元素给删除了。所以会出现上面的现象。

如果list中的元素是1个,3个或更多,则会报ConcurrentModificationException异常。所以平时还是不要用这种方式删除list中的元素。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值