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

开发数据库函数依赖算法时遭遇ArrayList与HashMap的ConcurrentModificationException

解决遍历集合时修改导致的ConcurrentModificationException问题

嘿,我之前在处理集合遍历+修改的场景时也踩过一模一样的坑,咱们来拆解一下问题,然后给出靠谱的解决方案!

为什么会出现这个异常?

你遇到的ConcurrentModificationException,本质上是因为你在使用迭代器遍历集合(比如ArrayList的增强for循环)的同时,直接调用了集合本身的remove()方法修改它。迭代器会维护一个修改计数,当它发现集合的实际修改次数和自己记录的不一致时,就会抛出这个异常——哪怕你是在单线程下操作,只要遍历和修改的方式不对,就会触发。

在你的场景里,就是遍历Map中List<String>类型的值时,直接调用了List.remove(),触发了迭代器的并发修改检测。

几种可行的解决方案

1. 使用迭代器的remove()方法(最标准的做法)

迭代器本身提供了安全的remove()方法,它会同步更新迭代器的修改计数,不会触发异常。把你的增强for循环改成用迭代器遍历:

// 假设你的Map结构是这样的
Map<String, List<String>> dependencyMap = ...;
List<String> headerList = ...;

for (String header : headerList) {
    // 遍历每个字符串的字符
    for (char c : header.toCharArray()) {
        String targetChar = String.valueOf(c);
        // 假设你要操作的是Map中某个key对应的List
        List<String> values = dependencyMap.get("你的目标Key");
        if (values == null) continue;
        
        // 使用迭代器遍历并安全移除
        Iterator<String> iter = values.iterator();
        while (iter.hasNext()) {
            String val = iter.next();
            // 这里替换成你的移除判断逻辑
            if (val.contains(targetChar)) {
                iter.remove(); // 用迭代器的remove方法,不会抛异常
            }
        }
    }
}

2. 使用Java 8+的removeIf()方法(更简洁)

如果你的移除逻辑可以用一个谓词表达式描述,List.removeIf()是更优雅的选择——它内部已经处理了安全遍历和修改的逻辑:

for (String header : headerList) {
    for (char c : header.toCharArray()) {
        String targetChar = String.valueOf(c);
        List<String> values = dependencyMap.get("你的目标Key");
        if (values == null) continue;
        
        // 一行搞定安全移除
        values.removeIf(val -> val.contains(targetChar));
    }
}

3. 遍历集合的副本,修改原集合

如果上面两种方式不适合你的场景,还可以先把原集合复制一份,遍历这个副本,然后修改原集合。这样原集合的修改不会影响遍历过程:

for (String header : headerList) {
    for (char c : header.toCharArray()) {
        String targetChar = String.valueOf(c);
        List<String> values = dependencyMap.get("你的目标Key");
        if (values == null) continue;
        
        // 创建原集合的副本
        List<String> valuesCopy = new ArrayList<>(values);
        for (String val : valuesCopy) {
            if (val.contains(targetChar)) {
                values.remove(val); // 遍历副本,修改原集合
            }
        }
    }
}

额外提醒

如果你的Map本身也在被遍历的同时修改(比如遍历Map的key时添加/删除key),那还要注意Map的安全遍历——比如用entrySet()的迭代器,或者使用ConcurrentHashMap(但要注意,ConcurrentHashMap只是保证Map本身的线程安全,它的value如果是ArrayList的话,还是要按照上面的方法处理List的遍历修改)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:48:48