Выполнение этого кода:
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());
}
}
Распечатает значение 100.
Почему это печатает это значение?
s.remove(i - 1);
Строка выше попытается удалить объекты Integer
из набора, потому что все целочисленные вычисления в Java имеют результаты int
(или long
). Поскольку набор содержит объекты Short
, метод remove()
не будет иметь никакого эффекта.
Это (и подобные проблемы) является основной причиной, по которой практически никогда не следует использовать short
(и, тем более, Short
). Использование реализации Set
для содержания автобоксированных чисел приводит к огромным (легко 1000%) накладным расходам, поэтому бессмысленно пытаться сэкономить место, используя Short
, а не Integer
.
Проблема в том, что remove(i-1)
вызывает метод remove
с объектом Integer
, так как i-1
имеет тип int
(который автобоксируется в Integer
).
Чтобы убедиться, что вы вызываете remove
с объектом Short
, используйте следующее:
s.remove((short) (i - 1));
Обратите внимание, что метод добавления обычно имеет тип boolean add (E o)
, поэтому в вашем случае Set метод добавления займет короткое время, тогда как метод удаления не имеет общего типа boolean remove (Объект o)
, поэтому i - 1
автоматически преобразуется в целое число. Для любого значения i new Short (i) .equals (new Integer (i))
всегда будет ложным.
Обратите внимание, что если вы попробуете s.add (i - 1);
, вы получите ошибку компилятора, потому что i - 1
становится экземпляром Integer, а типы Integer и Short не совпадает.
Тип i - 1
- int
, поэтому он автоматически преобразуется в целое число.
Обычно можно ожидать, что универсальная коллекция предотвратит выполнение операций с аргументами неправильного типа, но интерфейс для Set
немного нечеткий.
Поскольку метод remove из Set
принимает объект
, а не E
, компилятор не предупреждает вы, что удаляете другой тип, отличный от того, что содержит набор.
Чтобы заставить его быть Short
, приведите числовое значение к (short)
. (преобразование в (Short)
не допускается, и вам придется преобразовать числовое значение, чтобы использовать Short.valueOf
)