打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
为什么不能在foreach循环进行remove/add操作?

废话少说,直接上测试代码:

public class ForeachTest {    public static void main(String[] args){        List<String> list = new ArrayList<>();        list.add("hello");        list.add("hello1");        list.add("hello2");//        for (int i = 0; i < list.size(); i++) {        for(String s:list){            list.remove("hello");            System.out.println(s);        }    }}

结果如下: 

 

 然后换一种遍历方式:

public class ForeachTest {    public static void main(String[] args){        List<String> list = new ArrayList<>();        list.add("hello");        list.add("hello1");        list.add("hello2");        for (int i = 0; i < list.size(); i++) {//        for(String s:list){            list.remove("hello");            System.out.println(list.get(i));        }    }}

 结果如下:


以上是两种测试的对比现象(结果),那么既然有了结果接下来就要分析原因了。

控制台抛异常首先定位异常抛出的地方,通过查看ArrayList源码可以得知异常触发点为:

可知,异常的原因是因为modCount != expectedModCount导致的。

接下来就是分别查看这两个参数的含义和可以修改他们的操作了。

  • modCount:是AbstractList的一个成员变量:
    protected transient int modCount = 0;

    但是ArrayList是继承AbstractList的,这里modCount的修饰符是protected,所以是可以被subclass继承的。
    继续查看源码,对modCount的英文解释为:

    The number of times this list has been <i>structurally modified</i>.翻译:记录该list结构被修改的次数。查看源码中该变量的修改情况,发现就是在add/remove的时候,修改了modeCount的值。
  • expectedModCount:是ArrayList的一个内部类的成员变量


    说明:这里我们知道增强for底层的实现还是通过Iterator实现的,所以这里就不难理解为什么出现在这个地方了。

  • 在Iterator遍历开始就设置了两个参数相等,那么是什么情况导致了两个参数不等呢?
    前面我们知道在对集合进行add和remove的时候会修改modCount的值,而我们整个iterator都没有修改expectedModCount的值,所以在我们使用增强for遍历的时候,如果进行add/remove的操作,就会导致两个参数不等,然后抛出异常。

fail-fast机制:以上我们是从代码层面分析出了,为什么抛出异常,但是我们其实还不是很清楚为什么要这么设计。其实这是Java的fail-fast 机制,即快速失败机制,是java集合(Collection)中的一种错误检测机制。

详细解释如下:


上面我们基本了解了异常原因和原理,接下来的问题就是我们该如何在业务中处理这种情况呢?

  1. 第一种方式:我们使用一般的for循环即可;
  2. 第二种方式:我们使用Iterator自带的remove方法进行操作,因为自带的方法是同步了modCount和expecteModCount的;
  3. 第三种方式:使用Java8中的filter;
  4. 第四种方式:新建一个集合来装过滤后的数据(这种方式比较消耗内存,不推荐使用);
  5. 第N种方式:已经知道原因和原理了,其实处理方式就很灵活了,可以自己想想其他方式了,哈哈!!!
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
为什么阿里巴巴禁止在 foreach 循环里进行元素的 remove/add 操作
解决ArrayList的ConcurrentModificationExceptio
[J] 再次遭遇 Iterator 遍历 ArrayList 元素时执行删除操作
java的Iterator源码浅析
服了!JAVA 中简单的 for 循环这么坑。。。
从ArrayLis遍历删除的bug
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服