Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

I am getting java.util.ConcurrentModificationException thrown while using HashMap

How do i remove the key value pair in the code below comparing with elements in 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);
    }
}
like image 839
ashwinsakthi Avatar asked Jul 18 '26 04:07

ashwinsakthi


2 Answers

As per javadoc

ConcurrentModificationException may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible

 transactionLogMap.remove(bigDecimal);

Instead of for loop use Iterator and call remove on iterator.

Example:

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

OR

You may consider using ConcurrentHashMap

Note: Typed in code, use as reference. There may be syntax errors.

like image 160
kosa Avatar answered Jul 19 '26 20:07

kosa


The problem is in these lines

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

You are iterating through the transactionLogMap whilst also directly modifying the underlying Collection when you call transactionLogMap.remove, which is not allowed because the enhanced for loop cannot see those changes.

The correct solution is to use the Iterator:

Iterator<BigDecimal> it = transactionLogMap.keySet().iterator();//changed for syntax correctness
while (it.hasNext()) {
    BigDecimal bigDecimal = it.next();
    if(!inScopeActiveRegionIdSet.contains(bigDecimal)) {
        it.remove();
    }
}
like image 36
fommil Avatar answered Jul 19 '26 21:07

fommil