首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ConcurrentModificationException - checkForComodification(ArrayList.java)

ConcurrentModificationException - checkForComodification(ArrayList.java)
EN

Stack Overflow用户
提问于 2014-10-21 13:22:31
回答 3查看 11.3K关注 0票数 1

对于下面的带有Hash Map的java程序,抛出了ConcurrentModification异常,我在程序中标记了抛出异常的行。

我现在跳过了向HashMap中插入数据的登录

代码语言:javascript
复制
import java.util.ArrayList;
 import java.util.HashMap;

 public class MainClass {

     public static void main(String[] args) {

         ArrayList<HashMap<String, ArrayList<String>>> arrMain = new ArrayList<HashMap<String, ArrayList<String>>>();

         HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();

         ArrayList<String> strings = new ArrayList<String>();

         // Code to build the above Maps with all required Data, Skipped for Now

         //******************Scenario 1****************
         for (HashMap<String, ArrayList<String>> dataMap : arrMain) { //ConcurrentModification Exception
             for (String s : dataMap.get("Key")) {
                 ArrayList<String> newStrings = new ArrayList<String>();
                 newStrings.addAll(dataMap.get("Key")); 
                 newStrings.add("New String");
                 dataMap.put("Key", newStrings);
             }

         }

         //******************Scenario 2****************
         for (HashMap<String, ArrayList<String>> dataMap : arrMain) {//ConcurrentModification Exception
             for (String s : dataMap.get("Key")) {
                 dataMap.get("Key").add("New String"); 
             }

         }

     }

 }

错误:

代码语言:javascript
复制
java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
    at java.util.ArrayList$Itr.next(ArrayList.java:791)
EN

回答 3

Stack Overflow用户

发布于 2014-10-21 13:25:05

当你试图在迭代时修改集合时,你会得到ConcurrentModificationException。您可以尝试使用Iterator来避免这种情况。

例如:使用MapIterator

代码语言:javascript
复制
    Map<String, String> map = new HashMap<>();
    map.put("a", "a1");
    map.put("b", "b1");
    map.put("c", "c1");
    System.out.println(map);
    Iterator it = map.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry pairs = (Map.Entry) it.next();
        System.out.println(pairs.getKey() + " = " + pairs.getValue());
        it.remove(); // no a ConcurrentModificationException
    }
    System.out.println(map);

输出:

代码语言:javascript
复制
{b=b1, c=c1, a=a1}
b = b1
c = c1
a = a1
{}
票数 3
EN

Stack Overflow用户

发布于 2014-10-21 13:33:23

您在代码中标记了2个ConcurrentModificationException点,但只有一个是可重现的和合理的。

第二个:

代码语言:javascript
复制
for (HashMap<String, ArrayList<String>> dataMap : arrMain) {
     for (String s : dataMap.get("Key")) { // HERE 
         dataMap.get("Key").add("New String"); 
     }
}

dataMap.get("Key")返回一个ArrayList,您可以在for循环中向其添加另一个元素:

代码语言:javascript
复制
dataMap.get("Key").add("New String");

在添加一个元素(修改它)之后,for循环将继续。在遍历元素的过程中,将元素添加到列表中。这会导致ConcurrentModificationException (在幕后,增强的for使用列表的迭代器遍历其元素,如果在迭代器创建后修改了列表,则迭代器next()方法将抛出此异常)。

在代码中的第一点,你指出了ConcurrentModificationException,它不会引起异常,因为你迭代了一个列表,然后修改了另一个列表,一个在for循环中创建的新列表。但我怀疑这是你真正想做的。

票数 3
EN

Stack Overflow用户

发布于 2014-10-21 13:33:13

您可以使用ConcurrentHashMap

一个哈希表,支持完全并发的检索和可调整的预期更新并发性。该类遵循与Hashtable相同的功能规范,并且包含与Hashtable的每个方法相对应的方法版本。但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。在依赖于Hashtable线程安全性而不依赖于其同步细节的程序中,这个类完全可以与Hashtable互操作。

你可以使用迭代器。迭代器被设计为一次只能由一个线程使用。它们不抛出ConcurrentModificationException.

ConcurrentModificationException

代码语言:javascript
复制
public class ConcurrentModificationException
             extends RuntimeException

当不允许对对象进行并发修改时,检测到此类修改的方法可能会抛出此异常。例如,当一个线程正在迭代集合时,通常不允许另一个线程修改该集合。

另请参阅

  • Concurrent Hash Map article
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26479394

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档