美文网首页
foreach的集合原理,以及注意事项

foreach的集合原理,以及注意事项

作者: momdiemg | 来源:发表于2020-01-02 11:57 被阅读0次
List<String> list = new ArrayList<String>();

list.add("1");
list.add("2");

for (String item : list) {
    if ("1".equals(item)) {
        list.remove(item);
        System.out.println("执行if语句成功");
    }
}

直接运行这段代码是没什么问题的,数组list能成功删除元素1,也能打印对应语句。

但是,我们进行如下任意一种操作:
若把list.remove(item)换成list.add(“3”); 报错
若在第6行添加list.add(“3”); 报错
若把if语句中的“1”换成“2”, 报错

why?

1. 202012-113226.jpg

这涉及多线程操作,Iterator是不支持多线程操作的,List类会在内部维护一个modCount的变量,用来记录修改次数。也就每次add或者remove它的值都会加1

在 foreach 循环中执行 list.add(item);,对 list 对象的 modCount 值进行了修改,而 list 对象的迭代器的 expectedModCount 值未进行修改, 但此时调用了foreach的next()方法之后,就用进行校验checkForComodification(),发现不一样抛出异常。,因此抛出了ConcurrentModificationException异常。

3.若把if语句中的“1”换成“2”为什么报错呢?
至于为什么删除“1”就可以呢,原因在于foreach和迭代器的hasNext()方法,foreach这个语法,实际上就是

while(itr.hasNext()){
    itr.next()
}
所以每次循环都会先执行hasNext(),那么看看ArrayList的hasNext()是怎么写的:

public boolean hasNext() {
    return cursor != size;
}

cursor代表当前迭代器的游标,如果删除了,cursor!=size为false ,hasNext直接返回false,就不执行next()了所以,不会抛出异常。

如果删除的话有两种办法

//通过迭代器移除等于11的元素
    Iterator<String> iterator = list.iterator();
    while(iterator.hasNext()) {
        String item = iterator.next();
        if("11".equals(item)) {
            iterator.remove();
        }
    }


//jdk1.8移除等于11的元素
list.removeIf(item -> "11".equals(item));

相关文章

网友评论

      本文标题:foreach的集合原理,以及注意事项

      本文链接:https://www.haomeiwen.com/subject/lbgnoctx.html