I am getting java.util.ConcurrentModificationExcep

2019-08-26 22:11发布

问题:

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

回答1:

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


回答2:

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.



回答3:

You cannot remove items from a collection while you are iterating over it. This causes the exception you're getting.

When you call:

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

What happens under the hood is that you're creating an iterator for collectionOfX, and iterating until you explicitly break from the cycle or hasNext() for the iterator is false.

If you need to remove items from the collection during the iteration, you need to replace that foreach construct with an explicit call to the Iterator. Something like:

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.
}


回答4:

Alternatively, if inScopeActiveRegionIdSet is smaller in size, it might be shorter and faster to iterate it instead:

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