什么?ArrayList我用增强for循环删除居然没报错?

笔者在阅读阿里巴巴Java开发手册时看到这样一段话:

不要在 foreach 循环里进行元素的 remove/add 操作。remove 元素请使用Iterator 方式,如果并发操作,需要对 Iterator 对象加锁
正例:

List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
	String item = iterator.next();
	if (删除元素的条件) {
		iterator.remove();
	}
}

反例:

for (String item : list) {
	if ("1".equals(item)) {
		list.remove(item);
	}
}

说明:以上代码的执行结果肯定会出乎大家的意料,那么试一下把“1”换成“2”,会是同样的结果吗?

笔者疑惑,什么意思,难道不是所有的增强for删除元素都会报错吗?记得是modCount != expectedModCount的时候会报错呀

于是笔者实现了一下,发现…

        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");

        for (String item : list) {
            if ("1".equals(item)) {
                list.remove(item);
            }
        }
        System.out.println(list);

发现居然…
在这里插入图片描述
一条小绿条震惊了我
在这里插入图片描述
然后我执行第二套代码,也就是把1换成2

        List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");

        for (String item : list) {
            if ("2".equals(item)) {
                list.remove(item);
            }
        }
        System.out.println(list);

在这里插入图片描述
呼~报错了,是我满意的结果。

于是,我决定debug一下发生了什么,第一套代码为什么不会报错呢。

首先进到remove方法
在这里插入图片描述
很合理,进到fastRemove方法了
在这里插入图片描述
modCount++,移动元素,让空出的位置值null让GC清理,很合理,1 被删除了。
在这里插入图片描述
然后回来,return true,进行下一个遍历。增强for是会用ArrayList的内部类,来判断是否有下一个元素,cursor是一个游标,判断是否遍历到头了。在这里插入图片描述
可以看到,由于刚才已经删除了“1”,所以size为1,而cursor由于是到索引1了,haxNext的判断游标与长度是相等的,在他看来遍历结束了,返回false。于是遍历结束,这样还没进入到modCount和expectedModCount的比较,遍历就已经退出~

让我们再来看看第二套代码

由于第一个值是“1”,不相等,所以直接进入第二个循环

在这里插入图片描述
跟前面一样,会用ArrayList的内部类判断是否遍历结束
在这里插入图片描述
这里游标为1,size为2,所以不相等,为true

接下来是调用next方法,这个方法依旧是ArrayList的内部类Itr持有
在这里插入图片描述
进入checkForComodification方法
在这里插入图片描述
可以看到,由于之前没有删除操作,所以这一步是ok的,不会报错。

继续走next剩余的方法,没有问题。
在这里插入图片描述

接下来因为相等了,执行remove方法在这里插入图片描述
在这里插入图片描述
执行fastRemove方法,modCount的值变化
在这里插入图片描述
然后增强for循环继续
在这里插入图片描述
发现hasNext依旧成立,因为游标cursor为2,而长度为1
于是执行next方法,首先执行checkForComodification
在这里插入图片描述
modCount不等于expectedModCount,抛出异常
在这里插入图片描述

总结:
原来如此,代码1之所以没有报错,原来是因为它没有进入到modCount和expectedModCount的判断就结束了。但是只要我们明确不能在增强for循环删除、插入元素,还是ok的~。

果然,要了解底层,还是得自己看看源码才知道。

  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值