Marin Jurjević
Marin Jurjević

Reputation: 23

How to remove element from list that is being iterated in another method?

I have a class member list I am iterating over in following method:

public void deselectAll() {
    Iterator<GraphicalObject> iterator = selectedObjects.iterator();
    while(iterator.hasNext())
    {
        iterator.next().setSelected(false);
    }
}

Method setSelected() will cause current element to be removed in subsequent calls that setSelected() triggers. Is there a way I can remove current element somewhere out of this method and continue iterating normally?

EDIT: I see question is ambiguous a bit. Here's example showing problem in context ( I left out irrelevant code):

public class Model {

     private List<GraphicalObject> selectedObjects;

     private final GraphicalObjectListener listener = new GraphicalObjectListener() {
           @Override
           public void graphicalObjectSelectionChanged(GraphicalObject go) {
                int index = selectedObjects.indexOf(go);
                if(go.isSelected()) {
                     if(index == -1) {
                          selectedObjects.add(go);
                      } else {
                          return;
                      }
                } else {
                      if(index != -1) {
                          selectedObjects.remove(index);
                      } else {
                          return;
                      }
                }
                notifyListeners();
          }
    };

    public void deselectAll() {
        Iterator<GraphicalObject> iterator = selectedObjects.iterator();
        while(iterator.hasNext()){
                iterator.next().setSelected(false);
        }
    } 

}

public abstract class AbstractGraphicalObject implements GraphicalObject {

@Override public void setSelected(boolean selected) { this.selected = selected; notifySelectionListeners(); } public void notifySelectionListeners() { for (GraphicalObjectListener listener : listeners) { listener.graphicalObjectSelectionChanged(this); } }

}

Upvotes: 2

Views: 138

Answers (2)

Kim Kern
Kim Kern

Reputation: 60357

You could iterate over a copy of the list, so that you don't run into ConcurrentModificationExceptions. If you're using Java 8:

public void deselectAll() {
  List<GraphicalObject> toBeDeselected = selectedObjects.stream().collect(Collectors.toList());
  toBeDeselected.forEach(obj -> obj.setSelected(false));
}

Upvotes: 1

fps
fps

Reputation: 34460

If you want to both remove the element from the list and call setSelected(false) on the removed element, you could do it as follows:

public void deselectAll() {
    Iterator<GraphicalObject> iterator = selectedObjects.iterator();
    while(iterator.hasNext()) {
        GraphicalObject g = iterator.next();
        iterator.remove();    // removes g from selectedObjects
        g.setSelected(false); // deselects g
    }
}

Of course, in your setSelected method you shouldn't remove the element from the list.

Note: invoking remove on the iterator works as long as the collection selectedObjects supports removal through an iterator, but this is the case with most common collections, such as ArrayList.

Upvotes: 1

Related Questions