-2

Iterating over a list of user defined class using Iterator class of enhanced for loop gives java.util.ConcurrentModificationException exception but when using the traditional for loop it runs just fine.

Actually I am trying to implement my own hashmap using Java. Below is the perfectly fine working code when I am using indexed for loop:

class MyHashMap {
    public final int MAX_VALUE = 1009; // any big prime number
    LinkedList<Node> buckets[];
    public MyHashMap() {
        buckets = new LinkedList[MAX_VALUE];
        for (int i = 0;i<buckets.length;i++)
            buckets[i] = new LinkedList<Node>();
    }
    
    public void put(int key, int value) {
        int index = key % MAX_VALUE;
        LinkedList<Node> list = buckets[index];
        if (get(key) != -1) remove(key);   // if the key is available then remove it // same as update
        Node entry = new Node(key, value); //otherwise
        list.add(entry);  
        
    }
    
    public int get(int key) {
        int index = key % MAX_VALUE;
        List<Node> list = buckets[index];
        if(list==null)return -1;
        for(Node n : list){
            if(n.key == key)return n.val;
        }
        return -1;
    }
    
    public void remove(int key) {
        int index = key % MAX_VALUE;
        LinkedList<Node> list = buckets[index];
        if(list == null)return;
       ** //synchronized(this){
        for(int i=0;i<list.size();i++){
            Node n = list.get(i);
            if(n.key == key){
                list.remove(n);
                break;
            }**
        }
    //}
    }
}
class Node{
    public int key;
    public int val;
    public Node(int key, int val){
        this.key=key;
        this.val=val;
    }
}
/**
 * Your MyHashMap object will be instantiated and called as such:
 * MyHashMap obj = new MyHashMap();
 * obj.put(key,value);
 * int param_2 = obj.get(key);
 * obj.remove(key);
 */

I also tried using the enhanced loop inside a synchronized block to no avail.

I have 3 questions for this behaviour:

  1. Why does the traditional loop works and enhanced loop and iterator does'nt?
  2. What exactly does the java.util.ConcurrentModificationException exception signify?
  3. Why does using the enhanced for loop inside the synchronized block (to ensure the loop iteration is locked for a single thread at a time) not help with this java.util.ConcurrentModificationException exception?
  • I am trying to implement my own hashmap using Java.
  • I tried using iterator in place of enhanced for loop but it does'nt works.
  • I also tried putting the enhanced for loop inside a synchronized block as you can see in the code but still no luck.
  • 3
    1. Did you check [the documentation](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/util/LinkedList.html#:~:text=The%20iterators%20returned,will%20throw%20a%20ConcurrentModificationException.)? 2. Why do you keep iterating after you removed the one element you were looking for? 3. What do you mean with “by-pass this exception”? According to your own statement at the end, putting the enhanced for loop inside a synchronized block had no effect at all. Which is expected. – Holger May 23 '23 at 12:19
  • I was trying to use the synchronized block to see if I could get rid of java.util.ConcurrentModificationException which occurs mainly when any object of Collections class is being modified by a thread while other thread tries to read it. – alamshahbaz16497 May 23 '23 at 18:50
  • I checked the documentation and as mentioned it kind of explains (as @hunter also explained below) why the iterator would fail. But why does the enhanced loop fails while the indexed loop works fine? – alamshahbaz16497 May 23 '23 at 18:56
  • 2
    The enhanced for loop uses an `Iterator`. It’s a simplified syntax for a common use case, but doesn’t differ from an `Iterator` based loop in the compiled code (except for arrays). – Holger May 24 '23 at 06:46

2 Answers2

2

even though the exception name is ConcurrentModificationException , it is has nothing to do with concurrent executions in your case.

the code you posted will never throw this ConcurrentModificationException exception. instead of indexed for loop in the "remove" method, if you use enhanced for loop, it will throw this exception.

once iterator is created , you can not modify the list , if it happens iterator modcount and list modcount will differ, so in next usage of the iterator will throw this exception.

Ex: this kind of code will throw this exception

for (Object o : list) 
{
  list.remove(o);
}

Why indexed loop works?

for (int i = 0; i < list.size(); i++) 
{
   list.remove(i);
}

it doesn't use iterator. "for loop" and list has no real connection, it just evaluate list.size() for each turn in the loop and list is accessed using the index. but above code ends up with completely incorrect result. when first iteration of the loop remove the 0th index, element in the 1st index become the 0th index element. so loop will never hit on the first indexed item which is now the 0th index item. after completed the for loop, there will be still items in the list(half size).

hunter
  • 3,963
  • 1
  • 16
  • 19
  • Yes, I figured this ConcurrentModificationException exception has nothing to do with concurrent execution in my case. But still I couldn't figure why the enhanced loop fails while the indexed loop is working fine – alamshahbaz16497 May 23 '23 at 18:52
  • @alamshahbaz16497 - answer was edited and i tried to explain that part as well – hunter May 24 '23 at 04:48
0

According to the docs for ConcurrentModificationException,

[I]f a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.

I'm sure you can answer all 3 of your questions by just reading the docs yourself: https://docs.oracle.com/javase/8/docs/api/?java/util/ConcurrentModificationException.html

carter
  • 59
  • 5
  • Yes, I checked the documentation. But where is it specified that why and how would the indexed loop works while the enhanced loop fails? – alamshahbaz16497 May 23 '23 at 18:57