How to avoid ConcurrentModificationException / How to remove an item from an ArrayList while iterating over it

Many times it happens when you are iterating over an ArrayList and you want to remove items from this list based on some condition. For Example, there is a list of students and you want to remove those students whose result is “Fail”. Code for this requirement is as simple as below :

// studentList is a list of students
for(Student student : studentList) {
   // check if result of student is "Fail"
   if(student.getResult().equals("Fail")) {
      // remove it from list
      studentList.remove();
   }
}

The above code seems a piece of cake but it is not that way. It will not work and throw a java.util.ConcurrentModificationException. This exception is thrown when a Collection is modified while it is being iterated. In the above scenario, how would you remove students from a list. Is there no way for it ? There is a way, in fact, there are many ways. This post will guide you through all of those.

Method 1 : Using a copy of List
Create a new list initialized with the elements of the list to be iterated. Then iterate the original list and when an element needs to be deleted from the list, delete it from the copy made initially and NOT from the original list (which is being iterated) as below :

// studentList is a list of students
List copyList = new ArrayList(studentList);
for(Student student : studentList) {
    // check if result of student is "Fail"
    if(student.getResult().equals("Fail")) {
        // remove it from copy of list
        copyList.remove();
    }
}

Method 2 : Using iterator
Iterate over the list using a java.util.Iterator and if you want to remove any object from the list, remove it using iterator’s remove method only.

// studentList is a list of students
Iterator iterator = studentList.iterator();
// loop over the list using iterator
while(iterator.hasNext()) {
   Student student = iterator.next(); 
   // check if result of student is "Fail"
   if(student.getResult().equals("Fail")) {
       // remove it using iterator
       iterator.remove();
   }
}

iterator() method of an ArrayList returns an instance of java.util.Iterator which can be used to loop over the items of the list. Its hasNext() method returns true if there are more elements to iterate in the list and its next() method returns the next element in iteration. An element from the list can be safely removed by using iterator’s remove() method. This method will remove the last element returned by iterator’s next() method.

Method 3 : Using ListIterator

This method is similar to above method except that it uses java.util.ListIterator in place of java.util.Iterator. A ListIterator can be retrieved by using listIterator() method of java.util.ArrayList class as :

// studentList is a list of students
ListIterator listIterator = studentList.listIterator();
// loop over the list using iterator
while(listIterator.hasNext()) {
   Student student = iterator.next(); 
   // check if result of student is "Fail"
   if(student.getResult().equals("Fail")) {
      // remove it using iterator
      listIterator.remove();
   }
}

A ListIterator also has same methods as an Iterator. Its remove() method also removes an element returned by next() method.

Method 4 : Using new method added in Java 8

Java 8 has introduced a new method by which all elements matching a certain condition can be removed from the list in one go. There is no need of iterating over the list and using any of the methods explained above.
Java 8 release has added a new method removeIf() in java.util.Collection interface which takes a java.util.Predicate as an argument. In simple words, it takes a condition on which you want to remove elements from the list. This condition will be tested on all elements of the list and those elements for which this condition returns true will be removed from the list. An example will make it more clear.

// studentList is a list of students
studentList.removeIf(s -> s.getResult().equals("Fail"));

The expression s -> s.getResult().equals("Fail") is a Lambda expression which returns true for elements whose result field is “Fail”. The letter ‘s’ is just a variable and any sequence of characters can be used in place of it. It is just like a variable used as a counter in loop.

This method is the most easiest and compact method. But it can only be used if you are using Java 8.

Let’s tweak in :

  1. java.util.ArrayList has an overloaded constructor which takes another collection as argument. ArrayList is initialized to the contents of the collection passed in the constructor.
  2. remove() method of java.util.Iterator removes the last element returned by a call to its next() method.
  3. java.lang.IllegalStateException is thrown if you call iterator’s remove() method before calling next(). This is an unchecked exception.
  4. java.util.ListIterator has methods to traverse a list in reverse direction unlike the java.util.Iterator.
  5. removeIf() method returns true if any elements were removed from the list else returns false.
  6. removeIf() method is a default method in java.util.Collection interface. Methods with default access modifier in an interface have an implementation.

 

Revert for any sort of feedback, comments and suggestions. Keep visiting and coding !!!

Leave a Reply