2

I'm reading "Effective Java" by Joshua Bloch now and when I read item 41 "Use overloading judiciously" I was confused because of the example used there. I tried it on computer and it indeed does what it does in the book. But I don't understand why!

Here's this example:

public class SetList {
    public static void main(String[] args) {
        Set<Integer> set = new TreeSet<Integer>();
        List<Integer> list = new ArrayList<Integer>();
        for (int i = -3; i < 3; i++) {
            set.add(i);
            list.add(i);
        }
        for (int i = 0; i < 3; i++) {
            set.remove(i);
            list.remove(i);
        }
        System.out.println(set + " " + list);
    }
}

It outputs:

[-3, -2, -1] [-2, 0, 2]

I understand that list.remove() in this example should remove by index but it doesn't! After list was filled with values it was: [-3, -2, -1, 0, 1, 2]. So, when we remove 0, 1 and 2 elements we should stay with [0, 1, 2] and not with [-2, 0, 2]. What's going on there?

Charles Goodwin
  • 6,402
  • 3
  • 34
  • 63
mykola
  • 1,736
  • 5
  • 25
  • 37
  • 1
    This question is not a duplicate of the question "Properly removing an Integer from a List". That question relates to the pitfall of calling remove(int index) when remove(Object o) was intended, or vice versa. This question relates to the problem of removing multiple items from a list where the index of future items has been altered by the removal of preceding items. – timbo May 29 '15 at 04:36

2 Answers2

5

The list items are removed one-by-one and when items are removed from the list, the indexes of everything that comes after it are shifted back. This is why the indexes end up referring to different items than in the initial position.

If you can't see this easily, step through the code in a debugger or even "run" the list manipulations manually on paper, step by step.

Matti Virkkunen
  • 63,558
  • 9
  • 127
  • 159
5

This is just elaborating on Matti's answer really. I couldn't get this clearly in a comment.

Look at the list after elements are added:

[-3 -2 -1 0 1 2]

Remove element 0

[-2 -1 0 1 2]

Remove element 1 - which is now the same as the old element 2

[-2 0 1 2]

Remove element 2 - which is now the same as the old element 4

[-2 0 2]

There we go.

To make it even clearer, try reversing the order of the for and remove elements 2, then 1, then 0. You will get the answer you originally expected.

timbo
  • 1,533
  • 1
  • 15
  • 26