五年程序员使用ArrayList居然用forEach遍历删除元素?
创始人
2025-07-10 12:51:26
0

哈喽,大家好,我是了不起。

通常1-3年工作经验的程序员算是初级程序员,再往后基本上就是在编程领域有了一定经验的高级程序员了。

但是最近公司代码review时,我居然发现一个 5 年工作经验的程序员,使用 ArrayList 居然用 forEach 遍历删除元素?

1、现场还原

由于公司代码有一定敏感,我这里把代码进行脱敏,大家一起来看看:

public static void main(String[] args) {
    ArrayList list = new ArrayList<>(Arrays.asList("1", "2", "3"));
    list.forEach(item -> {
        if (item.startsWith("1")) {
            list.remove(item);
        }
    });
}

乍看之下,这段代码似乎没什么问题。但实际运行时,它会抛出ConcurrentModificationException异常。

这是为什么呢?我们运行这段代码,报错如下 :

图片图片

2、原因分析

其实 forEach 是一个语法糖,我们编译后的代码如下:

//这是一颗语法糖,编译后相当于:
for(Iterator i = lists.iterator();i.hasNext();){
    String s = (String)i.next();
    if(s.startsWith("1")){
        list.remove(s);
    }
}

然后这里的 i.next() 方法:

public E next() {
    checkForComodification();
    int i = cursor;
    if (i >= size)
        throw new NoSuchElementException();
    Object[] elementData = ArrayList.this.elementData;
    if (i >= elementData.length)
        throw new ConcurrentModificationException();
    cursor = i + 1;
    return (E) elementData[lastRet = i];
}
final void checkForComodification() {
    if (modCount != expectedModCount)
       throw new ConcurrentModificationException();
}

这样就很明了了,在Java中,当我们试图在遍历一个集合的同时修改它时,就会遇到ConcurrentModificationException。这是因为ArrayList的迭代器设计为快速失败(fail-fast),即在检测到集合在迭代期间被修改时立即抛出异常。

3、如何正确删除?

3.1 使用迭代器的remove方法

Iterator iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    if (item.startsWith("1")) {
        iterator.remove();
    }
}

这种方法可以保证在删除元素的同时不会破坏迭代器的状态。

3.2 使用removeIf方法

从Java 8开始,ArrayList引入了removeIf方法,这是删除元素的另一种便捷方式:

list.removeIf(item -> item.startsWith("1"));

3.3 收集需要删除的元素

最后一种方法是首先收集所有需要删除的元素,然后再进行删除:

List itemsToRemove = list.stream()
    .filter(item -> item.startsWith("1"))
    .collect(Collectors.toList());
list.removeAll(itemsToRemove);

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
Windows恶意软件20年“... 在Windows的早期年代,病毒游走于系统之间,偶尔删除文件(但被删除的文件几乎都是可恢复的),并弹...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
着眼MAC地址,解救无法享受D... 在安装了DHCP服务器的局域网环境中,每一台工作站在上网之前,都要先从DHCP服务器那里享受到地址动...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...