views:

150

answers:

4

Running this code:

    public class SomeSet {

    public static void main(String[] args) {

        Set<Short> s = new HashSet<Short>();

        for (short i = 0; i < 100; i++) {

            s.add(i);

            s.remove(i - 1);

        }

        System.out.println(s.size());

    }

}

Will print the value 100.

Why does it print this value?

+9  A: 
s.remove(i - 1);

The line above will attempt to remove Integer objects from the set, because all integer calculations in Java have int (or long) results. Since the set contains Short objects, the remove() method will not have any effect.

This (and similar problems) is the main reason why you should almost never use short (and, more so, Short). Using a Set implementation to contain autoboxed numbers incurs a massive (easily 1000%) overhead, so it's rather pointless to try and save space by using Short rather than Integer.

Michael Borgwardt
... or `float` or `double` ;-)
Joachim Sauer
+6  A: 

The problem is that remove(i-1) calls the remove method with an Integer object, since i-1 is of type int (which gets auto-boxed into an Integer).

To make sure that you call remove with a Short object use this:

s.remove((short) (i - 1));
Joachim Sauer
Or more explicitly s.remove(Short.valueOf(i-1));
Steve Kuo
@Steve: which wouldn't compile as you'd need an explicit cast as well. Making it more explicit but also more verbose.
Joachim Sauer
A: 

The type of i - 1 is int, so it gets autoboxed to an Integer.

Normally you'd expect a generic collection to prevent you performing operations which have arguments of the wrong type, but the interface to Set<E> is a bit loose.

Because the remove method of Set<E> takes an Object rather than an E, the compiler doesn't warn you that you're removing a different type to what the set contains.

To force it to be a Short, cast the numeric value to (short). (casting to (Short) isn't allowed, and you'd have to cast the numeric value to use Short.valueOf)

Pete Kirkham
A: 

Note that the add method is generically typed boolean add(E o) so in your case of Set the add method will take a short, whereas the remove method is not generically typed boolean remove(Object o) so i - 1 autoboxes to a Integer. For any value of i new Short(i).equals(new Integer(i)) will always be false.

Note that if you try s.add(i - 1); you will get a compiler error because i - 1 becomes an instance of Integer and the types Integer and Short do not match.

krock