我有2个哈希图:HashMap<String, Word> hmSmall, hmBig
。每个映射都是多对一。因此,基于某些标准,我必须删除与两个哈希映射中的特定值相对应的所有映射。为此,我正在关注this回答。
问题是我在迭代hashmap时仍然得到ConcurrentModificationException
。
以下是代码:
for (Iterator<Word> it = hmSmall.values().iterator(); it.hasNext(); i++) {
Word value = it.next();//java.util.ConcurrentModificationException here
String key = value.getKey();
if (hmBig.containsKey(key)) {
// if big contains less then remove from big
// else it.remove
if (hmBig.get(key).getTotalOccurances() < value
.getTotalOccurances()) {
hmBig.values().removeAll(
Collections.singleton(hmBig.get(key)));
} else {
// it.remove(); not using this based on https://stackoverflow.com/a/30214164/848377
hmSmall.values().removeAll(Collections.singleton(value));
}
}
}
有简单的出路吗?
答案 0 :(得分:0)
您必须在迭代时通过Iterator.remove()
删除,以避免ConcurrentModificationException
。
答案 1 :(得分:0)
您的问题是,当您使用Iterator类迭代HashMap时,您将通过删除元素来更改HashMap的大小...
您可以将要删除的对象存储在单独的集合中,然后在循环后删除所有对象。
中的示例Map<String, String> map = new HashMap<>();
map.put("a", "");
map.put("b", "");
map.put("c", "");
Set<String> set = new HashSet<> ();
set.add("a");
set.add("b");
map.keySet().removeAll(set);
System.out.println(map); //only contains "c"
答案 2 :(得分:0)
只需将removeAll调用放在循环外:
public static void main(String[] args) {
// The test map
final Map<String, String> map = new HashMap<String, String>();
map.put("Key1", "Value");
map.put("Key2", "Value");
map.put("Key3", "Value");
.
// Print the map to confirm it worked.
for(final String key : map.keySet()) {
map.values().removeAll(Collections.singleton("Value"));
System.out.println(key + " = " + map.get(key));
}
}
前一个会导致异常( ConcurrentModificationException )试试这个:
public static void main(String[] args) {
// The test map
final Map<String, String> map = new HashMap<String, String>();
map.put("Key1", "Value");
map.put("Key2", "Value");
map.put("Key3", "Value");
map.values().removeAll(Collections.singleton("Value"));
for(final String key : map.keySet()) {
System.out.println(key + " = " + map.get(key));
}
}
现在工作正常
答案 3 :(得分:0)
正如@Ejp建议的那样,Iterator#remove()
是摆脱ConcurrentModificationException
的最佳解决方案。
这里有类似的帖子Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop。
使用java8,您可以很好地使用removeIf()
方法。看看Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop
答案 4 :(得分:0)
所以这里的关键点是不要在迭代时改变hashmap的大小。因此,我没有删除循环中的条目,而是在一个arraylist中添加了密钥。当循环结束时,我遍历了那个arraylist并删除了与arraylist中的键对应的hashmap的条目。
以下是代码:
ArrayList<String> alsmallhm=new ArrayList<String>();
for (Iterator<Word> it = hmSmall.values().iterator(); it.hasNext(); i++) {
Word value = it.next();//java.util.ConcurrentModificationException here
String key = value.getKey();
if (hmBig.containsKey(key)) {
// if big contains less then remove from big
// else it.remove
if (hmBig.get(key).getTotalOccurances() < value
.getTotalOccurances()) {
hmBig.values().removeAll(
Collections.singleton(hmBig.get(key)));
} else {
// it.remove();
alsmallhm.add(key);
/*hmSmall.values().removeAll(Collections.singleton(value));*/
}
}
}
for(String s:alsmallhm){
hmSmall.values().removeAll(Collections.singleton(hmSmall.get(s)));
}