You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java11遍历列表时添加元素报ConcurrentModificationException有哪些解决方法?

异常触发原因

你遇到的ConcurrentModificationException,核心原因是在使用forEach遍历ArrayList时直接修改了列表的结构(新增/删除元素)。Java的ArrayList采用fail-fast设计,迭代过程中会校验列表的修改次数,一旦检测到结构变化就会直接抛出该异常。

除此之外你的代码还有三个隐藏问题:

  1. 两个Person实例共享了同一个hobbies列表,修改任意一个的爱好会同步影响另一个,不符合常规业务逻辑
  2. Collections.singletonList返回的是不可变列表,后续如果尝试修改这个列表会直接抛出UnsupportedOperationException
  3. hobby.getMyHobby().toLowerCase()没有生效:String是不可变类,需要调用setMyHobby把转换后的小写值赋值回去

可行解决办法

  • 方案1:遍历过程中先收集待新增的元素,遍历结束后统一添加
    这是最常用的无额外依赖的方案,不会触发fail-fast校验,性能损耗极小,适配绝大多数业务场景
  • 方案2:使用普通for下标循环遍历爱好列表
    下标遍历不依赖迭代器,修改列表结构不会触发异常,但要注意新增元素时的下标越界问题
  • 方案3:将存储爱好的ArrayList替换为java.util.concurrent.CopyOnWriteArrayList
    该并发容器专门为频繁遍历、少量修改的场景设计,遍历过程中修改结构不会抛出异常,但修改时会复制整个列表,内存开销稍高

修正代码示例(采用方案1实现)

import lombok.Data;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class Test {

    public static void main(String[] args) throws IOException {

        List<Person> myList = new ArrayList<>();
        // 给每个Person单独初始化hobbies列表,避免共享
        List<Hobby> hobbies1 = new ArrayList<>();
        hobbies1.add(new Hobby("SKI"));
        hobbies1.add(new Hobby("reading"));
        Person p = new Person("R", hobbies1);

        List<Hobby> hobbies2 = new ArrayList<>();
        hobbies2.add(new Hobby("SKI"));
        hobbies2.add(new Hobby("reading"));
        Person p1 = new Person("M", hobbies2);

        myList.add(p);
        myList.add(p1);
        myList.forEach(currentElement -> {
            if (Objects.isNull(currentElement.getHobbies())) {
                // 如果后续需要修改爱好列表,不要直接用singletonList,套一层ArrayList保证可修改
                currentElement.setHobbies(new ArrayList<>(Collections.singletonList(new Hobby("NOTHING"))));
            } else {
                List<Hobby> toAdd = new ArrayList<>();
                currentElement.getHobbies().forEach(hobby -> {
                    if (hobby.getMyHobby().equals("SKI")) {
                        // 先收集待新增的爱好,不直接修改遍历中的原列表
                        toAdd.add(new Hobby("SAILING"));
                    } else {
                        // 字符串不可变,需要赋值回去修改才会生效
                        hobby.setMyHobby(hobby.getMyHobby().toLowerCase());
                    }
                });
                // 遍历结束后统一添加所有待新增元素
                currentElement.getHobbies().addAll(toAdd);
            }
        });
    }

    @Data
    static class Person {
        String name;
        List<Hobby> hobbies;

        public Person(String name, List<Hobby> hobbies) {
            this.name = name;
            this.hobbies = hobbies;
        }
    }

    @Data
    static class Hobby {
        String myHobby;

        public Hobby(String myHobby) {
            this.myHobby = myHobby;
        }
    }
}

内容的提问来源于stack exchange,提问作者freecoderw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 06:45:03