0

A ConcurrentModificationException was returned removing an entry from a map but I am unable to see what's wrong.

    Iterator<String> mapIterator = this.attributeMap.keySet().iterator();
    while (mapIterator.hasNext())
    {
        String attributeName = mapIterator.next();
        if (attributeName.matches(pattern))
        {
            mapIterator.remove();
        }
    }
Dangel
  • 21
  • 1
  • 2
  • 1
    Are there multiple threads accessing the Map concurrently? – Eran Jan 23 '19 at 09:00
  • As an aside (which likely won't fix the CME by itself), you can also do `this.attributeMap.keySet().removeIf(k -> k.matches(pattern))`. – Andy Turner Jan 23 '19 at 09:01
  • @VictorGalvez then you need to somehow ensure exclusive access to the map wherever it is read or written to. – Andy Turner Jan 23 '19 at 09:03
  • Yes, there's multiple threads accessing and removeIf() is only compatible with Java 8. – Dangel Jan 23 '19 at 09:05
  • It's simple. We prevent concurrent access to the Map with the synchronized-keyword. – Torben Jan 23 '19 at 09:08
  • Possible duplicate of [ConcurrentModificationException and a HashMap](https://stackoverflow.com/questions/602636/concurrentmodificationexception-and-a-hashmap) – Torben Jan 23 '19 at 09:09

2 Answers2

1

You can check this out on some details about CME: https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible. For example, it is not generally permissible for one thread to modify a Collection while another thread is iterating over it. In general, the results of the iteration are undefined under these circumstances. Some Iterator implementations (including those of all the general purpose collection implementations provided by the JRE) may choose to throw this exception if this behavior is detected. Iterators that do this are known as fail-fast iterators, as they fail quickly and cleanly, rather that risking arbitrary, non-deterministic behavior at an undetermined time in the future.

Here are some solutions provided by Baeldung, linked below:

  1. Using an Iterator Directly
  2. Not removing during iteration
  3. Using removeIf()
  4. Filtering using Streams

You can check his site out for the details for each solution to avoid CME: https://www.baeldung.com/java-concurrentmodificationexception

Hope this helps.

Ben
  • 66
  • 5
1

In this case the line mapIterator.next() throws ConcurrentModificationException .

The reason behind this is:
There is an int variable modCount which provides the number of times list size has been changed, this value is used in every next() call to check for any modifications in a function checkForComodification().
if mapIterator.next() found change in modCount while iteration object then it will throw ConcurrentModificationException .

To avoid this please follow the below points:

  1. You can convert the list to an array and then iterate on the array. This approach works well for small or medium size list but if the list is large then it will affect the performance a lot.

  2. You can lock the list while iterating by putting it in a synchronized block. This approach is not recommended because it will cease the benefits of multithreading.

  3. If you are using JDK1.5 or higher then you can use ConcurrentHashMap and CopyOnWriteArrayList classes. It is the recommended approach.

TheSprinter
  • 1,523
  • 17
  • 30