Правильное удаление целого из списка <Integer>
Здесь хорошая ошибка, с которой я только что столкнулся.
Рассмотрим список целых чисел:
List<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(6);
list.add(7);
list.add(1);
Любое образованное предположение о том, что происходит при выполнении list.remove(1)
? Что насчет list.remove(new Integer(1))
? Это может вызвать некоторые неприятные ошибки.
Каков правильный способ разграничения между remove(int index)
, который удаляет элемент из заданного индекса и remove(Object o)
, который удаляет элемент по ссылке при работе со списками целых чисел?
Главное здесь рассмотреть один @Nikita, упомянутый - точное сопоставление параметров имеет преимущество перед автоматическим боксом.
Ответы
Ответ 1
Java всегда вызывает метод, который наилучшим образом соответствует вашему аргументу. Автоматический бокс и неявное восходящее движение выполняются только в том случае, если нет метода, который можно вызвать без каста/автоматического бокса.
Интерфейс List указывает два метода удаления (обратите внимание на именование аргументов):
-
remove(Object o)
-
remove(int index)
Это означает, что list.remove(1)
удаляет объект в позиции 1 и remove(new Integer(1))
удаляет первое вхождение указанного элемента из этого списка.
Ответ 2
Вы можете использовать кастинг
list.remove((int) n);
и
list.remove((Integer) n);
Не имеет значения, если n - это int или Integer, метод всегда будет называть тот, который вы ожидаете.
Использование (Integer) n
или Integer.valueOf(n)
более эффективно, чем new Integer(n)
, поскольку первые два могут использовать кеш Integer, тогда как позже будет всегда создавать объект.
Ответ 3
Я не знаю о "правильном" способе, но способ, который вы предложили, работает очень хорошо:
list.remove(int_parameter);
удаляет элемент в заданном положении и
list.remove(Integer_parameter);
удаляет данный объект из списка.
Это потому, что VM сначала пытается найти метод, объявленный с точно таким же типом параметра, и только затем пытается autoboxing.
Ответ 4
list.remove(4)
является точным соответствием list.remove(int index)
, поэтому он будет вызываться. Если вы хотите вызвать list.remove(Object)
, выполните следующие действия: list.remove((Integer)4)
.
Ответ 5
Любое образованное предположение о том, что происходит при выполнении list.remove(1)? Как насчет list.remove(новый Integer (1))?
Нет необходимости гадать. Первый случай приведет к вызову List.remove(int)
, и элемент в позиции 1
будет удален. Второй случай приведет к вызову List.remove(Integer)
, и элемент, значение которого равно Integer(1)
, будет удалено. В обоих случаях компилятор Java выбирает ближайшую совпадающую перегрузку.
Да, здесь есть путаница (и ошибки), но это довольно необычный случай использования.
Когда два метода List.remove
были определены в Java 1.2, перегрузки не были двусмысленными. Проблема возникла только с введением генериков и автобоксинга в Java 1.5. На заднем плане было бы лучше, если бы одному из методов удаления присвоено другое имя. Но уже слишком поздно.
Ответ 6
Обратите внимание, что даже если виртуальная машина не сделала правильные вещи, что она делает, вы все равно можете обеспечить правильное поведение, используя тот факт, что remove(java.lang.Object)
работает с произвольными объектами:
myList.remove(new Object() {
@Override
public boolean equals(Object other) {
int k = ((Integer) other).intValue();
return k == 1;
}
}
Ответ 7
Просто мне понравилось следующее, как было предложено #decitrig в принятом ответе на первый комментарий.
list.remove(Integer.valueOf(intereger_parameter));
Это помогло мне. Еще раз спасибо #decitrig за ваш комментарий. Это может помочь кому-то.
Ответ 8
Ну вот трюк.
Здесь можно привести два примера:
public class ArrayListExample {
public static void main(String[] args) {
Collection<Integer> collection = new ArrayList<>();
List<Integer> arrayList = new ArrayList<>();
collection.add(1);
collection.add(2);
collection.add(3);
collection.add(null);
collection.add(4);
collection.add(null);
System.out.println("Collection" + collection);
arrayList.add(1);
arrayList.add(2);
arrayList.add(3);
arrayList.add(null);
arrayList.add(4);
arrayList.add(null);
System.out.println("ArrayList" + arrayList);
collection.remove(3);
arrayList.remove(3);
System.out.println("");
System.out.println("After Removal of '3' :");
System.out.println("Collection" + collection);
System.out.println("ArrayList" + arrayList);
collection.remove(null);
arrayList.remove(null);
System.out.println("");
System.out.println("After Removal of 'null': ");
System.out.println("Collection" + collection);
System.out.println("ArrayList" + arrayList);
}
}
Теперь посмотрим на результат:
Collection[1, 2, 3, null, 4, null]
ArrayList[1, 2, 3, null, 4, null]
After Removal of '3' :
Collection[1, 2, null, 4, null]
ArrayList[1, 2, 3, 4, null]
After Removal of 'null':
Collection[1, 2, 4, null]
ArrayList[1, 2, 3, 4]
Теперь проанализируем вывод:
-
Когда 3 удаляется из коллекции, он вызывает метод remove()
коллекции, который принимает Object o
как параметр. Следовательно, он удаляет объект 3
.
Но в объекте arrayList он переопределяется индексом 3 и, следовательно, удаляется 4-й элемент.
-
По той же логике удаления Object null в обоих случаях удаляется во втором случае.
Итак, чтобы удалить номер 3
, который является объектом, нам явно нужно передать 3 как object
.
И это может быть сделано путем литья или обертывания с использованием класса-оболочки Integer
.
Например:
Integer removeIndex = Integer.valueOf("3");
collection.remove(removeIndex);
Ответ 9
Простой код Java Объяснение для визуализации разницы между ArrayList.remove(Object o)
и ArrayList.remove(int index)
КОД:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(7);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
for (int a = 0; a < list.size(); a++) {
System.out.print("" + list.get(a));
}
System.out.print(" ");
//CASE 1: We are removing data object 7.
list.remove(new Integer(7));
for (int a = 0; a < list.size(); a++) {
System.out.print("" + list.get(a));
}
System.out.print(" ");
//CASE 2: Again we are removing data object 7.
list.remove(new Integer(7));
for (int a = 0; a < list.size(); a++) {
System.out.print("" + list.get(a));
}
System.out.print(" ");
//CASE 3: We are removing data at index 1
list.remove(1);
for (int a = 0; a < list.size(); a++) {
System.out.print("" + list.get(a));
}
ВЫХОД:
1274567
124567
12456
1456
ОБЪЯСНЕНИЕ:
CASE 1: Мы удаляем первый объект Integer с данными 7.
CASE 2: Затем мы снова делаем то же, что и в CASE 1
из оставшихся данных.
CASE 3: Мы удаляем данные в позиции индекса.
ЗАКЛЮЧЕНИЕ:
Пример ArrayList<Integer>
, используемый в приведенном выше java-коде:
ArrayList.remove(Integer object)
просто удалит конкретный объект Integer, который сначала встречается в ArrayList
.
Однако ArrayList.remove(int index)
всегда удаляет элемент массива в заданной позиции индекса.
БОЛЬШЕ:
Мы не можем объявить ArrayList<int>
, потому что он int
является основным типом данных. Любой класс, который имеет базовый класс Object
, указан только в типичном типе ArrayList
. например: ArrayList<String>
, ArrayList<Integer>
и т.д.