ivanciprian
ivanciprian

Reputation: 83

Iterator inside Iterator ConcurrentModificationException

I am having the following problem:

Given an ArrayList (let's call it list), how can I "double-iterate" through it without getting ConcurrentModificationException?

Here's what I've tried:

iterator out = list.iterator();
iterator in;
while(out.hasNext()){
    ...
    in = list.iterator();
    while(in.hasNext()){
        ...
        if(something)
             in.remove();
    }

Upvotes: 1

Views: 1626

Answers (4)

tmarwen
tmarwen

Reputation: 16354

The Iterator instance provided through a call to List#iterator method preserves a count scalar allowing to detect external changes to the Collection container.

When an element is removed from the collection by any other mean than going through the same Iterator#remove(T) call, the count is not updated behind the scenes. Therefore when you request for the #next() element through the iterator instance, the count is checked against an expected value and if both values does not match (since an element has been removed through another iterator) a ConcurrentModificationException is thrown (even though you may be working in a single threaded environment).

The solution whould be, as @Michael stated, to keep track of the container elements that should be removed then perform a bulk delete:

Collection<Object> temp = new ArrayList<>();
iterator out = list.iterator();
iterator in;
while (out.hasNext()) {
    // ...
    in = list.iterator();
    while (in.hasNext()) {
        // ...
        if(something)
             // just mark the element for deletion
             temp.add(in.next());
    }
}

// delete all the obsolete elements
list.removeAll(temp);

Upvotes: 1

Binu
Binu

Reputation: 784

You are trying to modify an iterator. It will give you concurrentModification exception.

In java 8 you can easily remove it using list.removeIf(someCondition)

Try this link java8 collections

Upvotes: 1

Michael
Michael

Reputation: 44090

You can't do that. A potential solution might be to mark objects to be removed, for example:

final List<Foo> toRemove = new ArrayList<>();

for (Foo a : list)
{
    for (Foo b : list)
    {
        if (something)
        {
            toRemove.add(b);
        }
    }
}
list.removeAll(toRemove);

You may need some additional checks to see that the object isn't already marked for removal. It's impossible to say given how vague your example is.

Upvotes: 2

gati sahu
gati sahu

Reputation: 2626

In collection once iterator creator If you try to modify the content not through same iterator it will throw concurrent exception.If you required some special kind of iterator then you can go ahead and implement your own.

Upvotes: 0

Related Questions