2012-07-30 86 views
0

如何在下面的代码中比较HashMap中的元素,删除键值对?我在使用HashMap时抛出java.util.ConcurrentModificationException

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

回答

2

的问题是在这些线路

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(); 
    } 
} 
8

作为每javadoc的

ConcurrentModificationException可以由已经检测到对象的并发修改方法被抛出当这样的修改是不允许

transactionLogMap.remove(bigDecimal); 

代替for loop使用Iterator并在迭代器上调用remove。

例子:

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

OR

您可以考虑使用ConcurrentHashMap

注:键入的代码,使用作为参考。可能有语法错误。

2

无法删除的项目从一个集合。这会导致你得到的异常。

当你拨打:

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

引擎盖下会发生什么事是你正在创造collectionOfX一个迭代器,并迭代,直到明确地从周期或hasNext()的迭代器是假突破。

如果您需要在迭代期间从集合中删除项目,则需要用对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. 
} 
0

或者,如果inScopeActiveRegionIdSet尺寸较小,这可能是更短,更快的迭代它来代替:

for (BigDecimal bigDecimal : inScopeActiveRegionIdSet) { 
    transactionLogMap.remove(bigDecimal); 
} 
相关问题