[java] Removing items from a list

While looping through a list, I would like to remove an item of a list depending on a condition. See the code below.

This gives me a ConcurrentModification exception.

for (Object a : list) {
    if (a.getXXX().equalsIgnoreCase("AAA")) {
        logger.info("this is AAA........should be removed from the list ");
        list.remove(a);
    }
}

How can this be done?

This question is related to java collections

The answer is


Besides all the excellent solutions offered here I would like to offer a different solution.

I'm not sure if you're free to add dependencies, but if you can, you could add the https://code.google.com/p/guava-libraries/ as a dependency. This library adds support for many basic functional operations to Java and can make working with collections a lot easier and more readable.

In the code I replaced the type of the List by T, since I don't know what your list is typed to.

This problem can with guava be solved like this:

List<T> filteredList = new Arraylist<>(filter(list, not(XXX_EQUAL_TO_AAA)));

And somewhere else you then define XXX_EQUAL_TO_AAA as:

public static final Predicate<T> XXX_EQUAL_TO_AAA = new Predicate<T>() {
    @Override
    public boolean apply(T input) {
        return input.getXXX().equalsIgnoreCase("AAA");
    }
}

However, this is probably overkill in your situation. It's just something that becomes increasingly powerful the more you work with collections.

Ohw, also, you need these static imports:

import static com.google.common.base.Predicates.not;
import static com.google.common.collect.Collections2.filter;

You can't and shouldn't modify a list while iterating over it. You can solve this by temporarely saving the objects to remove:

List<Object> toRemove = new ArrayList<Object>();
for(Object a: list){
    if(a.getXXX().equalsIgnoreCase("AAA")){
        toRemove.add(a);
    }
}
list.removeAll(toRemove);

for (Iterator<String> iter = list.listIterator(); iter.hasNext(); ) {
    String a = iter.next();
    if (...) {
        iter.remove();
    }
}

Making an additional assumption that the list is of strings. As already answered, an list.iterator() is needed. The listIterator can do a bit of navigation too.


//first find out the removed ones

List removedList = new ArrayList();
for(Object a: list){
    if(a.getXXX().equalsIgnoreCase("AAA")){
        logger.info("this is AAA........should be removed from the list ");
        removedList.add(a);

    }
}

list.removeAll(removedList);

You cannot do it because you are already looping on it.

Inorder to avoid this situation use Iterator,which guarentees you to remove the element from list safely ...

List<Object> objs;
Iterator<Object> i = objs.iterator();
while (i.hasNext()) {
   Object o = i.next();
  //some condition
    i.remove();
}