I have a program that is single-threaded that uses a Map where items are removed one by one while iterating. I have read that iterator can be used here to avoid ConcurrentModificationException
but why not use ConcurrentHashMap instead which seems to be much cleaner?
My code:
private final Map<Integer, Row> rowMap;
.....
private void shutDown() {
for (Integer rowNumber : rowMap.keySet()) {
deleteRow(rowNumber)
}
}
....
For my scenario, using a iterator means declaring it final so closeRow() and deleteRow() methods have access to it for removing it. Additionally, the iterator.remove() method does not return the value of the item being removed which is necessary in my case.
My question is, what is the most efficient way to do it so it doesn't throw ConcurrentModificationException? Is it using an iterator or making rowMap a ConcurrentHashMap?
It's a fairly straightforward iterator pattern.
Iterator<Map.Entry<Integer,Row>> it = rowMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer,Row> ent = it.next();
Integer key = ent.getKey();
Row row = ent.getValue(); // before the remove
it.remove();
// ... do what you want with key and row;
}
So, we're iterating through the map with an explicit iterator, which allows us to use the iterator's remove
method during iteration. We're iterating over the "entry set" view of the map, which allows us to retrieve both key and value from the single iterator.
public Set<Map.Entry<K,V>> entrySet()
Returns a Set view of the mappings contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation, or through the setValue operation on a map entry returned by the iterator) the results of the iteration are undefined.