首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Android ConcurrentModificationException:遍歷 Map 時修改的正確姿勢

     編輯:程式設計疑難解答

異常原因:迭代器檢測到結構性修改

在 for (String key : map.keySet()) 或 iterator 遍歷過程中呼叫 map.put(),會導致迭代器的 modCount 與預期不符,拋出 ConcurrentModificationException。

錯誤代碼模式


// ❌ 遍歷時直接 put 新 key
for (String key : maps.keySet()) {
    if (key.equals(target)) {
        maps.get(key).add(value);
    } else {
        maps.put(newKey, newList); // 修改結構 → 拋出異常
    }
}

三種修正方案

方案一:先收集待處理項,遍歷結束後統一修改(推薦)


List keysToAdd = new ArrayList<>();
for (String key : maps.keySet()) {
    if (key.equals(target)) {
        maps.get(key).add(value);
    } else {
        keysToAdd.add(newKey); // 記錄下來
    }
}
for (String k : keysToAdd) {
    maps.put(k, newList);
}

方案二:使用 Iterator.remove() 唯一合法修改方式


Iterator> it = maps.entrySet().iterator();
while (it.hasNext()) {
    Map.Entry entry = it.next();
    if (shouldRemove(entry.getKey())) {
        it.remove(); // 唯一允許在遍歷中修改結構的操作
    }
}
// 遍歷結束後再 put 新資料

方案三:Java 8+ ConcurrentHashMap / computeIfAbsent


// 線程安全且支援原子更新
ConcurrentHashMap map = new ConcurrentHashMap<>();
map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);

最佳實踐原則

  1. 遍歷與修改分離:先查詢/標記,後增刪。
  2. 用 ConcurrentHashMap 取代 HandledMap(多執行緒環境必備)。
  3. 單執行緒 也遵循「只讀遍歷,寫入延後」習慣,避免未來移植到多執行緒出錯。

記住:**fail-fast 迭代器是保護你,不是刁難你**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved