对于带有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)
答案 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而另一个线程迭代它。