对于下面的带有Hash Map的java程序,抛出了ConcurrentModification异常,我在程序中标记了抛出异常的行。
我现在跳过了向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)发布于 2014-10-21 13:25:05
当你试图在迭代时修改集合时,你会得到ConcurrentModificationException。您可以尝试使用Iterator来避免这种情况。
例如:使用Map的Iterator
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);输出:
{b=b1, c=c1, a=a1}
b = b1
c = c1
a = a1
{}发布于 2014-10-21 13:33:23
您在代码中标记了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循环中创建的新列表。但我怀疑这是你真正想做的。
发布于 2014-10-21 13:33:13
您可以使用ConcurrentHashMap
一个哈希表,支持完全并发的检索和可调整的预期更新并发性。该类遵循与Hashtable相同的功能规范,并且包含与Hashtable的每个方法相对应的方法版本。但是,即使所有操作都是线程安全的,检索操作也不需要锁定,并且不支持以阻止所有访问的方式锁定整个表。在依赖于Hashtable线程安全性而不依赖于其同步细节的程序中,这个类完全可以与Hashtable互操作。
你可以使用迭代器。迭代器被设计为一次只能由一个线程使用。它们不抛出ConcurrentModificationException.
ConcurrentModificationException
public class ConcurrentModificationException
extends RuntimeException当不允许对对象进行并发修改时,检测到此类修改的方法可能会抛出此异常。例如,当一个线程正在迭代集合时,通常不允许另一个线程修改该集合。
另请参阅
https://stackoverflow.com/questions/26479394
复制相似问题