2

Hey programming student here.

I have a JavaFX application. I have a pane, and I want to remove all rectangles from it. Here is the code:

public Pane yard = new Pane();
...
for(int i = 0; i < yard.getChildren().size(); i++)
{
    if(yard.getChildren().get(i) instanceof Rectangle)
    {
        yard.getChildren().remove(i);
    }
 }

This works fine, sometimes. Other times it simply fails to remove anything. Thank you for your help.

  • `This works fine, sometimes. Other times it simply fails to remove anything` with this statement it is hard to tell exact problem. Debug step by step and try to understand why it fails. – Masudul Apr 30 '15 at 02:43
  • This has nothing to do with `instanceof`. [This Q&A provides a solution](http://stackoverflow.com/q/223918/335858). – Sergey Kalinichenko Apr 30 '15 at 02:45

4 Answers4

8

You're removing items as you move forward with the index, causing you to not consider certain items for removal.

You should solve this by using an Iterator instead:

Iterator<?> it = yard.getChildren().iterator();
while(it.hasNext()) {
    if(it.next() instanceof Rectangle) {
        it.remove();
    }
}

If you're using Java 8 you can do this instead which is more readable:

yard.getChildren().removeIf(Rectangle.class::isInstance);
Raniz
  • 10,882
  • 1
  • 32
  • 64
4

This is because you are calling remove within your for loop. You can't do that. If your for loop starts with 10 entries, the item at position 6 might be a rectangle to start with. However if you remove the 5th entry in your list, what was at position 6 will be at position 5 and be skipped over.

Example:

yard.getChildren[0] = square
yard.getChildren[1] = square
yard.getChildren[2] = rectangle
yard.getChildren[3] = rectangle.

you can see the item at index 2 will be removed, meaning that the size of yard.getChildren is now 3. Your counter i will also be 3 at this point. Therefore the for loop will stop, and the last rectangle wont be removed.

bcam909
  • 168
  • 11
2

This is happening because you are removing items from your list in a loop. If you need to remove items in a loop you should be using an iterator see: Calling remove in foreach loop in Java

Community
  • 1
  • 1
Magnus
  • 7,952
  • 2
  • 26
  • 52
1

When you remove item from collection then number of items in collection decreases too. So, you have to anticipate it and decrease working index to reflect such change:

public Pane yard = new Pane();
...
for(int i = 0; i < yard.getChildren().size(); i++)
{
    if(yard.getChildren().get(i) instanceof Rectangle)
    {
        yard.getChildren().remove(i--);// i-- is the change
    }
 }
Alex
  • 4,457
  • 2
  • 20
  • 59