Скажите, что я создаю один объект и добавляю его к моему ArrayList
. Если я затем создаю другой объект с точно тем же входом конструктора, будет contains()
метод оценивает два объекта быть тем же? Предположите, что конструктор не делает ничего забавного с входом, и переменные, сохраненные в обоих объектах, идентичны.
ArrayList<Thing> basket = new ArrayList<Thing>();
Thing thing = new Thing(100);
basket.add(thing);
Thing another = new Thing(100);
basket.contains(another); // true or false?
class Thing {
public int value;
public Thing (int x) {
value = x;
}
equals (Thing x) {
if (x.value == value) return true;
return false;
}
}
Это как class
должен быть реализован, чтобы иметь contains()
вернуть true
?
ArrayList реализует
интерфейс списка.
Если вы посмотрите на Javadoc для List
в методе contains
, то увидите, что он использует метод equals ()
для оценки того, два объекта одинаковы.
Он использует метод equals для объектов. Таким образом, если Thing не переопределит равенство и не использует переменные, хранящиеся в объектах для сравнения, он не вернет истину в методе contains ()
.
Как правило, вы также должны переопределять hashCode ()
каждый раз, когда вы переопределяете equals ()
, даже если только для повышения производительности. HashCode ()
решает, в какую «корзину» сортируется ваш объект при сравнении, поэтому любые два объекта, которые equal ()
оцениваются как истинные, должны возвращать один и тот же hashCode
значение ()
. Я не могу вспомнить поведение по умолчанию hashCode ()
(если он возвращает 0, тогда ваш код должен работать, но медленно, но если он возвращает адрес, ваш код не сработает). Я действительно помню много раз, когда мой код терпел неудачу, потому что я забыл переопределить hashCode ()
. :)
ArrayList использует метод equals, реализованный в классе (в вашем случае класс Thing), для сравнения равенства.
Другие авторы посвящены вопросу о том, как работает contains ().
Не менее важный аспект вашего вопроса - как правильно реализовать equals (). И ответ на этот вопрос действительно зависит от того, что составляет объектное равенство для этого конкретного класса. В приведенном вами примере, если у вас есть два разных объекта с x = 5, равны ли они? Это действительно зависит от того, что вы пытаетесь сделать.
Если вас интересует только равенство объектов, то реализация по умолчанию .equals () (предоставляемая Object) использует только идентичность (т.е. this == other). Если это то, что вы хотите, просто не реализуйте equals () в своем классе (пусть он наследуется от Object). Код, который вы написали, хотя и является правильным, если вы собираетесь использовать идентификацию, никогда не появится в реальном классе b / c, он не дает никаких преимуществ по сравнению с использованием реализации Object.equals () по умолчанию.
Если вы только начинаете заниматься этим, я настоятельно рекомендую книгу Джошуа Блоха «Эффективная Java». Это отличное чтение, и оно охватывает такого рода вещи (плюс то, как правильно реализовать equals (), когда вы пытаетесь сделать больше, чем сравнения на основе идентичности)