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

自定义HashMap中增强for循环抛ConcurrentModificationException问题咨询

自定义HashMap遍历与修改的ConcurrentModificationException问题

在实现自定义HashMap时发现:使用传统索引for循环遍历并修改LinkedList桶时能正常运行,但用增强for循环(底层依赖Iterator)或直接使用Iterator遍历修改时,会抛出java.util.ConcurrentModificationException异常。即便将增强for循环放入同步块,问题依然存在。

以下是可正常运行的代码(remove方法使用传统for循环):

class MyHashMap {
    public final int MAX_VALUE = 1009; // 选用大质数作为桶数量
    LinkedList<Node> buckets[];
    public MyHashMap() {
        buckets = new LinkedList[MAX_VALUE];
        for (int i = 0; i < buckets.length; i++)
            buckets[i] = new LinkedList<Node>();
    }
    
    public void put(int key, int value) {
        int index = key % MAX_VALUE;
        LinkedList<Node> list = buckets[index];
        if (get(key) != -1) remove(key);   // 存在则先删除再更新
        Node entry = new Node(key, value);
        list.add(entry);  
    }
    
    public int get(int key) {
        int index = key % MAX_VALUE;
        List<Node> list = buckets[index];
        if(list == null) return -1;
        for(Node n : list){
            if(n.key == key) return n.val;
        }
        return -1;
    }
    
    public void remove(int key) {
        int index = key % MAX_VALUE;
        LinkedList<Node> list = buckets[index];
        if(list == null) return;
        // synchronized(this){
        for(int i = 0; i < list.size(); i++){
            Node n = list.get(i);
            if(n.key == key){
                list.remove(n);
                break;
            }
        }
        // }
    }
}
class Node{
    public int key;
    public int val;
    public Node(int key, int val){
        this.key = key;
        this.val = val;
    }
}
/**
 * Your MyHashMap object will be instantiated and called as such:
 * MyHashMap obj = new MyHashMap();
 * obj.put(key,value);
 * int param_2 = obj.get(key);
 * obj.remove(key);
 */

问题解答

1. 为何传统循环可行,而增强for循环和迭代器却不行?

Java的LinkedList属于**快速失败(fail-fast)**集合,内部维护了一个修改计数器modCount。

  • 传统索引for循环:直接通过索引访问元素,调用list.remove(n)会增加集合的modCount,但因为没有迭代器做一致性校验,所以不会触发异常(不过这种方式存在索引偏移风险,这里因找到元素后直接break才未暴露问题)。
  • 增强for/Iterator:遍历过程中,迭代器会记录当前的modCount,每次迭代都会检查该值是否与集合当前的modCount一致。调用list.remove(n)会修改集合的modCount,迭代器持有的旧值与新值不一致,下一次校验时就会抛出ConcurrentModificationException。

2. java.util.ConcurrentModificationException异常具体表示什么?

这个异常用于检测集合的并发修改问题,当集合在迭代过程中被非迭代器自身的方法修改时,就会抛出该异常。它的核心作用是提前发现修改不一致的bug,避免出现遍历结果异常或其他不可预期的行为。注意:它不仅会在多线程并发场景下触发,单线程中迭代时直接修改集合也会触发。

3. 为何在同步块中使用增强for循环(确保单线程锁定迭代)无法解决该异常?

同步块仅能保证同一时间只有一个线程访问代码块,但问题根源并非多线程并发,而是单线程中用Iterator遍历的同时,直接调用了集合的remove()方法修改集合。即便加了同步块,迭代器的modCount校验机制依然会触发:迭代器记录的modCount与集合实际的modCount因调用list.remove(n)产生差异,因此仍会抛出异常。只有使用迭代器自身的remove()方法,才会同步更新迭代器内部的modCount,避免触发异常。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 10:17:47