我在使用HashMap时抛出了java.util.ConcurrentModificationException

时间:2012-07-30 14:04:05

标签: java collections hashmap hashset

如何删除下面代码中的键值对与HashMap中的元素进行比较?

Map<BigDecimal, TransactionLogDTO> transactionLogMap = new HashMap<BigDecimal, TransactionLogDTO>();
for (BigDecimal regionID : regionIdList) {// Generation new logDTO
                                            // objects for each in scope
                                            // region
    transactionLogMap.put(regionID, new TransactionLogDTO());
}
Set<BigDecimal> inScopeActiveRegionIdSet = new HashSet<BigDecimal>();

for (PersonDTO personDTO4 : activePersons) {

    inScopeActiveRegionIdSet.add(personDTO4.getRegion());

}

for (BigDecimal bigDecimal : transactionLogMap.keySet()) {
    if (!inScopeActiveRegionIdSet.contains(bigDecimal)) {
        transactionLogMap.remove(bigDecimal);
    }
}

4 个答案:

答案 0 :(得分:8)

根据javadoc

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

ConcurrentModificationException

 transactionLogMap.remove(bigDecimal);

而不是for loop使用Iterator并在迭代器上调用remove。

示例:

Iterator iter = transactionLogMap.keySet().iterator();
while(iter.hasNext())
{
iter.remove();
}

OR

您可以考虑使用ConcurrentHashMap

注意:输入代码,用作参考。可能存在语法错误。

答案 1 :(得分:3)

问题出在这些方面

for (BigDecimal bigDecimal : transactionLogMap.keySet()) {
    if(!inScopeActiveRegionIdSet.contains(bigDecimal)) {
        transactionLogMap.remove(bigDecimal);
    }
}

您正在迭代transactionLogMap,同时在调用Collection时直接修改基础transactionLogMap.remove,这是不允许的,因为增强的for循环无法看到这些更改。

正确的解决方案是使用Iterator

Iterator<BigDecimal> it = transactionLogMap.keySet().iterator();//changed for syntax correctness
while (it.hasNext()) {
    BigDecimal bigDecimal = it.next();
    if(!inScopeActiveRegionIdSet.contains(bigDecimal)) {
        it.remove();
    }
}

答案 2 :(得分:2)

在迭代集合时,无法从集合中删除项目。这会导致您获得的例外情况。

致电时:

for(TypeX x: collectionOfX){ ... }

在幕后发生的事情是你为collectionOfX创建一个迭代器,并迭代直到你明确地从循环中断或迭代器的hasNext()为false。

如果需要在迭代期间从集合中删除项目,则需要使用对Iterator的显式调用替换该foreach构造。类似的东西:

Iterator<BigDecimal> iter = transactionLogMap.keySet().iterator();
while(iter.hasNext()) {
   BigDecimal bDecimal = iter.next();
   ...
   iter.remove(); //this will remove the current item from the collection, without raising an exception.
}

答案 3 :(得分:0)

或者,如果inScopeActiveRegionIdSet的尺寸较小,则可能会更短更快地迭代它:

for (BigDecimal bigDecimal : inScopeActiveRegionIdSet) {
    transactionLogMap.remove(bigDecimal);
}