#java #arraylist
#java #arraylist
Вопрос:
Когда я создаю ArrayList, подобный этому:
ArrayList<Integer> arr = new ArrayList
arr.add(1);
arr.add(3);
arr.add(34);
arr.add(13);
А затем я пытаюсь удалить элемент, передаваемый в качестве параметра new Integer(34)
.
arr.remove(new Integer(34));
Как работает эта строка?
Я создаю новый целочисленный объект?
Ни один элемент не должен быть удален, поскольку элемент, созданный в рамках метода, хранится в другой ячейке памяти, чем те, которые созданы в ArrayList. Верно?
Ответ №1:
Когда вы вызываете new Integer(34)
, ДА, определенно, он создает новый целочисленный объект. Но класс Integer переопределил equals
hashCode
методы and .
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
public int hashCode() {
return Integer.hashCode(value);
}
В вашем коде при вызове Arr.remove(new Integer(34))
метода вызывается from ArrayList remove(Object o)
.
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index )
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index )
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
Из приведенного выше кода вы можете видеть, когда o (Object)
значение не равно null, оно вызывает equals
проверку равенства и удаление объекта из списка. Таким образом, ваш объект удален, даже если он имеет другую ячейку памяти.
Еще один момент:
Рассмотрите возможность использования Integer.valueOf(34)
метода вместо new Integer(34)
. Integer.valueOf(34)
предоставит вам существующий экземпляр, если он уже создан в коде в каком-либо другом месте. Поскольку Integer является неизменяемым, это не создаст никаких проблем. Поэтому нет необходимости создавать новый объект каждый раз, используя new
ключевое слово.
Комментарии:
1. Большое вам спасибо, ваш ответ помог мне с моим вопросом. спасибо за включение кода, ваш ответ был лучшим
Ответ №2:
Внутренне java.util.ArrayList
используется .equals()
для сравнения при попытке удалить элемент из списка.
В вашем случае он удалит элемент со значением 34
, потому что это тип оболочки, для int
которого является an Object
.
Но если вы используете примитивный тип, он выдаст IndexOutOfBoundException
. Это связано с тем, что он вызовет другой remove()
метод, который принимает примитивный тип, и этот метод удалит элемент с индексом 34, которого нет в приведенном выше списке, и имеет только 4 элемента.
Кстати, вам не следует использовать метод конструктора для любых классов-оболочек в будущем, потому что он уже устарел с Java 9 и будет удален в Java 16. Вы должны использовать статический .valueOf()
метод при создании объекта-оболочки для примитивного типа.
Комментарии:
1. Большое вам спасибо, ваш ответ помог мне с моим вопросом.
Ответ №3:
Во-первых, вы могли бы просто привести к Integer
. Во-вторых, вы должны предпочесть соглашения об именовании Java. В-третьих, Arrays.asList
это гораздо менее неудобно. В-четвертых, вы можете распечатать List
. Наконец, (как вы и подозревали) здесь есть еще кое-что. byte
При использовании гарантированно кэшируются только значения в диапазоне new Integer(int)
(поэтому вам, вероятно, следует избегать этого и либо использовать, либо использовать Integer.valueOf(int)
).
List<Integer> al = new ArrayList<>(Arrays.asList(1, 3, 34, 13));
System.out.println(al);
al.remove((Integer) 34);
System.out.println(al);
Комментарии:
1. При использовании
Arrays.asList()
в приведенном выше вопросе он будет выданUnsupportedOperationException
при вызовеremove()
, потомуList
что класс, возвращаемыйArrays.asList()
неизменяемым.2. @MKTan Вот почему я использовал
new ArrayList<>(Arrays.asList(1, 3, 34, 13))
— он работает так, как ожидалось.3. Упс. Этого не видел. Извините.
Ответ №4:
According to Arraylist implementation remove method is based on equals().
For Integer equals is overridden as follow and based on int value but not on object reference
Целое число равно
public boolean equals(Object obj){
if(obj instanceof Integer){
return value==((Integer)obj).intValue();
}
return false;
}