Java: Different outputs when add/remove short and

2019-01-15 20:42发布

I wasn't sure on how to ask this question. But, what is the different between these 2 lines of code?

Set<Integer> a = new HashSet<Integer>();
for (int i = 0; i < 100; i++) {
    a.add(i);
    a.remove(i - 1);
}

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

I expected 99 to be the output

Output is 1


Set<Short> a = new HashSet<Short>();
for (Short i = 0; i < 100; i++) {
    a.add(i);
    a.remove(i - 1);
}

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

I expected 99 to be the output

Output is 100

3条回答
beautiful°
2楼-- · 2019-01-15 20:53

The first one will remove all number except 99 because the last number you remove is 98.

In the second you are trying to remove an Integer, but your type is Short, so it does not remove any element.

On the first one, you do add(i) the int is automatically converted to an Integer.

On the second if you had done the following:

Set<Short> a = new HashSet<Short>();
for (Short i = 0; i < 100; i++) {
     a.add(i);
     a.remove(i);
}

It would remove all the elements because you add a short and remove short, but because you did i - 1 you are not adding a short, but an integer.

查看更多
来,给爷笑一个
3楼-- · 2019-01-15 20:54

You can't remove Integer from Set of shorts without casting.

查看更多
干净又极端
4楼-- · 2019-01-15 21:05

The type of the expression i - 1 is int because all operands in an integer arithmetic expression are widened to at least int. Set<Short> has add(Short) and remove(Object) so there's no casting/autoboxing needed on the remove call. Therefore you are trying to remove Integers from a set of Shorts.

Note that for this reason it almost never makes sense to declare a Set<Number>:

final Set<Number> ns = new HashSet<>();
final short s = 1;
ns.add(s);
ns.add(s+0);
ns.add(s+0L);
System.out.println(ns); // prints [1, 1, 1]

As a bonus round, if you change the set implementation to TreeSet, the magic disappears and it throws a ClassCastException, giving away the trick.

Deep down, this issue has to do with the fact that equality is a symmetric relation, which must not distinguish the right hand side from the left hand side. These semantics are impossible to achieve with Java's single-dispatch methods.

查看更多
登录 后发表回答