ConcurrentModificationException - checkForComodification(ArrayList.java)

时间:2014-10-21 05:22:31

标签: java arraylist hashmap

对于带有Hash Map的Below java程序,抛出了ConcurrentModification异常,我已经标记了程序中抛出Exception的行。

我暂时跳过了将数据插入到HashMap的登录

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"); 
             }

         }

     }

 }

错误:

java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
    at java.util.ArrayList$Itr.next(ArrayList.java:791)

3 个答案:

答案 0 :(得分:3)

当您尝试在迭代时修改Collection时,您将获得ConcurrentModificationException。您可以尝试使用Iterator来避免这种情况。

例如:Iterator Map

    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);

Out put:

{b=b1, c=c1, a=a1}
b = b1
c = c1
a = a1
{}

答案 1 :(得分:1)

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

第二个:

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循环内的另一个元素:

dataMap.get("Key").add("New String");

在添加元素(修改它)之后,for循环将继续。您可以在迭代过程中向列表中添加一个元素。这导致ConcurrentModificationException(在增强的for下使用列表的迭代器来覆盖其元素,并且如果列表被修改,则迭代器next()方法抛出此异常,因为创建迭代器。)

代码中您指明ConcurrentModificationException的第一点,它不会导致异常,因为您遍历列表并修改了另一个列表,即您在for循环内创建的新列表。但我怀疑这是你真正想做的事情。

答案 2 :(得分:0)

您可以使用ConcurrentHashMap

  

一个哈希表,支持检索的完全并发和可更新的预期并发性。

     

该类遵循与Hashtable相同的功能规范,并包括与Hashtable的每个方法相对应的方法版本。

     

但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。

     

该类在依赖其线程安全但不依赖于其同步细节的程序中与Hashtable完全互操作。


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

ConcurrentModificationException

public class ConcurrentModificationException
             extends RuntimeException
  

当不允许进行此类修改时,检测到对象的并发修改的方法可能抛出此异常。

     

例如,一个线程通常不允许修改Collection而另一个线程迭代它。

另见