简体   繁体   中英

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

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.

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.

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();
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM