chrisapotek
chrisapotek

Reputation: 6227

Iterating through a list and allowing it to have an item removed at the same time (NOT ITERATOR)

ATTENTION: I CANNOT know if doSomething will remove the element or not. This is an exceptional case that my data structure needs to handle.

My problem is simples:

int size = list.size();
for(int i = 0; i < size; i++) {
   MyObj mo = list.get(i);
   mo.doSomething();
}

Now if doSomething() remove mo from the list, I eventually get an ArrayIndexOutOfBounds because the list has now shrunk.

What data structure should I use to allow iteration with the possibility of removing? I can NOT use an iterator here, in other words, I can NOT make doSomething return a boolean and call iterator.remove(). The data structure has to somehow handle the situation and continue to iterator through the rest of the elements still there.

EDIT: I CANNOT know if doSomething will remove the element or not. This is an exceptional case that my data structure needs to handle.

Part II => Making a smart listeners notifier to avoid code duplication everywhere

Upvotes: 2

Views: 352

Answers (3)

Christian Kuetbach
Christian Kuetbach

Reputation: 16060

I think you should change you doSomething(). If mo.doSomething() can remove mo from l, you mo must know your l.

You can change the code like this:

Create a valid flag, inside of your MyObj. Only listen if valid.

while(list.hasNext()) {
   MyObj mo = list.next()
   if(mo.isValid()){
       mo.doSomething();
   } else {
       list.remove();
   }
}

Upvotes: 0

Keppil
Keppil

Reputation: 46219

You can use an ArrayList, for example, as long as you update the index and size when something is removed.

List<MyObj> list = new ArrayList<MyObj>();
int size = list.size();
for(int i = 0; i < size; i++) {
    MyObj mo = list.get(i);
    mo.doSomething();
    if (size > list.size()) {
        size = list.size();
        i--;
    }
}

This only works if the item removed is the last one examined. For other changes to the list you will have to have more complicated logic.

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1500495

What data structure should I use to allow iteration with the possibility of removing?

The simplest option is to take a copy of the list and iterate over that instead:

List<MyObj> copy = new ArrayList<MyObj>(list);
for (MyObj mo : copy) {
    mo.doSomething();
}

Now it doesn't matter whether or not anything removes an idea from the original list - that won't change the copy of the list.

Another option is to use CopyOnWriteArrayList. You can then just iterate and remove or add items at will:

The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException. The iterator will not reflect additions, removals, or changes to the list since the iterator was created.

Upvotes: 2

Related Questions