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

ArrayList测试遭遇java.util.ConcurrentModificationException问题求助

解决ArrayList的ConcurrentModificationException问题

嘿,这个问题我之前也踩过坑!看起来你以为是在迭代前修改集合,但实际还是触发了并发修改异常,大概率是迭代器的创建时机比你想象的早,或者你用了隐式的迭代器(比如forEach循环)却没注意到。

常见原因分析

  • 迭代器已创建后修改集合:ArrayList的迭代器是快速失败(fail-fast)的,一旦迭代器被创建,之后如果集合被修改(除了迭代器自己的remove()/add()方法),迭代时就会抛出ConcurrentModificationException。你可能以为修改是在迭代前,但实际代码里迭代器已经提前初始化了,比如:
    List<String> list = new ArrayList<>();
    Iterator<String> iter = list.iterator(); // 这里已经创建了迭代器
    list.add("test"); // 迭代器创建后修改集合
    iter.next(); // 这里就会抛出异常,对应你的第23行
    
  • 隐式迭代器的坑:Java的for-each循环底层就是用迭代器实现的,如果你在for-each循环之前的某个地方,看似是“迭代前”但其实已经触发了迭代器的创建(比如某些方法内部偷偷用了迭代器,不过更常见的是你把修改操作放在了迭代器创建之后)。

解决方案

根据你的场景,有几个靠谱的解决办法:

  1. 确保修改完全在迭代器创建之前
    把所有集合修改操作放在迭代器初始化(或者for-each循环开始)之前,比如:
    List<Integer> nums = new ArrayList<>(Arrays.asList(1,2,3));
    nums.add(4); // 先完成所有修改
    // 再开始迭代
    for (Integer num : nums) {
        System.out.println(num);
    }
    
  2. 用迭代器自带的修改方法
    如果需要在迭代过程中修改集合,一定要用迭代器提供的remove()(或者ListIterator的add()/set())方法,这些方法会同步迭代器和集合的状态:
    List<Integer> nums = new ArrayList<>(Arrays.asList(1,2,3));
    ListIterator<Integer> iter = nums.listIterator();
    while (iter.hasNext()) {
        int num = iter.next();
        if (num == 2) {
            iter.remove(); // 安全修改,不会触发异常
        }
    }
    
  3. 改用CopyOnWriteArrayList
    如果你的场景确实需要在迭代时修改集合(比如多线程环境,或者逻辑上无法避免),可以用java.util.concurrent.CopyOnWriteArrayList,它通过复制底层数组来避免并发修改异常,不过适合读多写少的场景:
    List<String> list = new CopyOnWriteArrayList<>();
    list.add("a");
    // 迭代时修改也不会抛异常
    for (String s : list) {
        list.add("b");
    }
    

排查小技巧

你可以仔细检查第23行的上下文:

  • 看看迭代器(包括for-each循环)是不是在修改集合之前就已经被创建了?
  • 有没有在其他地方(比如之前的方法调用)偷偷创建了迭代器?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:10:32