javaiteratorconcurrentmodificationfail-fastjava-failsafe

java.util.ConcurrentModificationException while mutating an object


I am iterating over a List of CustomObject and while doing this iteration, I am mutating this object by adding a tag to tags list of this custom object. I am not adding or removing any CustomObject to or from customObjects (List). I am still getting java.util.ConcurrentModifcationException.

public class CustomObject {
    private List<Tag> tags;
    // Getter for Tag
    // Setter for tag
}

public class DummyClass {


  List<CustomObject> addMissingTag(List<CustomObject> customObjects) {
    for (CustomObject object:customObjects) { // line 5
      // following method adds a tag to tags list of CustomObject
      mutateObjectByAddingField(object); // line 7
      // Some Code      
    }
    return customObjects;
  }

  void mutateObjectByAddingField(CustomObject customObject) {//line 13
    Boolean found = false;
    for (Tag tag:customObject.getTags()) { // line 15
      if ("DummyKey".equalsIgnoreCase(tag.getKey())) {
        found = true;
        break;
      }
    }
    if (!found) {
      Tag tag = new Tag("DummyKey", "false");
      List<Tag> tags = customObject.getTags();
      tags.add(tag);
      customObject.setTags(tags);
    }
  }

}

Here is the stack trace:

java.util.ConcurrentModificationException: null
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) ~[?:1.8.0_131]
    at java.util.ArrayList$Itr.next(ArrayList.java:851) ~[?:1.8.0_131]
    at DummyClass.mutateObjectByAddingField(DummyClass.java:15)
    at DummyClass.addMissingTag(DummyClass.java:7)

Does this mean we can get ConcurrentModifcationException even if we just try to modify the object and not remove or add from/to the list/collection?


Solution

  • First, you are using a List type in the for loop to iterate the elements, so the enhanced for statement is equivalent to a for using an iterator, as mentioned here, because List implements Iterator. Also, it's obvious from the stack trace.

    When using Iterator, you can't make modifications on the list you are iterating, as mentioned GeeksForGeeks, you will get ConcurrentModificationException.

    So, to solve this issue, you can for example implement explicitly the for loop using integers like below:

     for (int i=0;i < customObjects.length(); i++) {
    
          CustomObject object = customObjects.get(i);
    
          // following method adds a tag to tags list of CustomObject
          mutateObjectByAddingField(object);
          // Some Code      
     }