为什么list不能在增强型循环遍历的时候用remove删除元素?

2 篇文章 0 订阅
1 篇文章 0 订阅

1、新人可能很常见的错误

public static void main(String[] args) {
    List<String> list= new ArrayList<>();
    list.add("1");
    list.add("2");
    list.add("3");

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

    System.out.println(list);
}

这是你会觉得没什么问题,逻辑很清晰,然后你就去跑了一下发现一个错误

java.util.ConcurrentModificationException异常了,翻译成中文就是:并发修改异常。

Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at shen.callable.XiaoMing.main(Main.java:33)

然后你换成删除2,你发现又可以了,再试下1又报错了,接下来我们就讲讲这是为什么?

 

2、分析为什么会出现这种情况

     我们打开target目录下找到这个文件的字节码文件你会发下它长这个样子去了

public static void main(String[] args) {
        List<String> list = new ArrayList();
        list.add("1");
        list.add("2");
        list.add("3");
        Iterator var2 = list.iterator();

        while(var2.hasNext()) {
            String s = (String)var2.next();
            if (s.equals("1")) {
                list.remove(s);
            }
        }

    }

从中我们可以看到list的增强型循环其实就是采用的iteratior形式,使用的核心方法是hasnext()和next()

(数组当然用不了迭代器就是普通的for循环,感兴趣的可以自己写一个看看)

我们接下来就看下list里的迭代器是如何实现的。

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

很简单,就是new了一个对象而已,那这个对象是什么呢?我们继续点下去。

我们发现就在这个方法的下面,这个Itr是arrayList的一个内部类。

当我们的代码执行到remove语句的时候

我们调用的是属于list的remove方法

这里我们的modCount++了

而当我们再一次循环的时候,调用的是list内部类itr的next方法,我们可以跟进看下

进入checkForComdification()方法

大家可以返回上面的Itr内部类的大致图看下expectedModCount会等于什么,

在我们调用的list的remove的时候,modCount++了,而我们的expectedModCount是等于最开始modCount值

所以这里明显不等于了,条件为真,

throw new ConcurrentModificationException();

其实这条线路不难推断,跟着报错点进去就能发现。

其实究其原因就是因为增强型循环对于list的遍历采用的是迭代器。

 

3、那我们如何在遍历的时候删除一个元素呢?

我已知的有俩种方法:

1、直接使用最简单的for循环遍历,条件判断一定要用i<list.size(),因为这样才会获得删除后的list大小,不然会报越界。

2、使用迭代器的remove方法

这里又要插几句了,为什么迭代器的remove反法有用呢?如果细心观察了源码的朋友应该能看到为什么。

这就是为什么迭代器的remove起作用的原因。

今天就说到这吧,最近在忙着找工作,因为只是普通二本的原因,困难重重,面试机会都没有。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值