2

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

}

  • Could you show an example of what you expect? Also possibly a duplicate of https://stackoverflow.com/questions/626671/java-how-to-remove-elements-from-a-list-while-iterating-over-adding-to-it?rq=1 – Ishnark Jun 08 '17 at 18:09
  • Do you want to iterate over the old list or the one with the removed element? – Sebastian Walla Jun 08 '17 at 18:15
  • As I understand the question, you could iterate over a copy of `selectedObjects` instead of iterating over it directly. I'm finding it a bit difficult to think of probable solutions with the way the question is written, though. It would help if you added a good [MCVE](https://stackoverflow.com/help/mcve) which showed something like what you're doing and why what you're asking for is really necessary. It may also be the case that this problem you've run in to is actually a hint that you should restructure the program rather than attempting to find a workaround. – Radiodef Jun 08 '17 at 18:19
  • This is really no a good idea as it could lead to things like a `ConcurrentModificationException`. Google "Remove Collection element while iterating" or check out a very detailed explanation in this post. https://stackoverflow.com/questions/10431981/remove-elements-from-collection-while-iterating – jiveturkey Jun 08 '17 at 18:23

2 Answers2

1

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.

fps
  • 33,623
  • 8
  • 55
  • 110
1

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));
}
Kim Kern
  • 54,283
  • 17
  • 197
  • 195