Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConcurrentModificationException when using iterator to remove entry

I have a simple piece of code that loops through a map, checks a condition for each entry, and executes a method on the entry if that condition is true. After that the entry is removed from the map. To delete an entry from the map I use an Iterator to avoid ConcurrentModificationException's.

Except my code does throw an exception, at the it.remove() line:

Caused by: java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.remove(Unknown Source) ~[?:1.8.0_161]
    at package.Class.method(Class.java:34) ~[Class.class:?]

After a long search I can't find a way to fix this, all answers suggest using the Iterator.remove() method, but I'm already using it. The documentation for Map.entrySet() clearly specifies that it is possible to remove elements from the set using the Iterator.remove() method.

Any help would be greatly appreciated.

My code:

Iterator<Entry<K, V>> it = map.entrySet().iterator();
while (it.hasNext()) {
    Entry<K, V> en = it.next();

    if (en.getValue().shouldRun()) {
        EventQueue.invokeLater(()->updateSomeGui(en.getKey())); //the map is in no way modified in this method
        en.getValue().run();
        it.remove(); //line 34
    }
}
like image 620
superbadcodemonkey Avatar asked Oct 26 '25 10:10

superbadcodemonkey


2 Answers

If you cannot change HashMap to ConcurrentHashMap you can use another approach to your code.

You can create a list of entries containing the entries that you want to delete and then iterate over them and remove them from the original map.

e.g.

    HashMap<String, String> map = new HashMap<>();
    map.put("1", "a1");
    map.put("2", "a2");
    map.put("3", "a3");
    map.put("4", "a4");
    map.put("5", "a5");
    Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
    List<Map.Entry<String, String>> entries = new ArrayList<>();

    while (iterator.hasNext()) {
        Map.Entry<String, String> next = iterator.next();
        if (next.getKey().equals("2")) {
            /* instead of remove
            iterator.remove();
            */
            entries.add(next);
        }
    }

    for (Map.Entry<String, String> entry: entries) {
        map.remove(entry.getKey());
    }
like image 161
aurelius Avatar answered Oct 29 '25 00:10

aurelius


Please use ConcurrentHashMap in place of HashMap as you are acting on the object in multiple threads. HashMap class isn't thread safe and also doesn't allow such operation. Please refer below link for more information related to this.

https://www.google.co.in/amp/s/www.geeksforgeeks.org/difference-hashmap-concurrenthashmap/amp/

Let me know for more information.

like image 30
Rohit Dodle Avatar answered Oct 28 '25 23:10

Rohit Dodle



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!