Как метод ArrayList в объекте () оценивает объекты? - PullRequest
286 голосов
/ 15 апреля 2010

Скажем, я создаю один объект и добавляю его в свой 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() return true?

Ответы [ 9 ]

321 голосов
/ 15 апреля 2010

ArrayList implements Интерфейс списка.

Если вы посмотрите на Javadoc для List на метод contains, вы увидите, что он использует метод equals(), чтобы оценить, совпадают ли два объекта.

52 голосов
/ 31 октября 2012

Я думаю, что правильные реализации должны быть

public class Thing
{
    public int value;  

    public Thing (int x)
    {
        this.value = x;
    }

    @Override
    public boolean equals(Object object)
    {
        boolean sameSame = false;

        if (object != null && object instanceof Thing)
        {
            sameSame = this.value == ((Thing) object).value;
        }

        return sameSame;
    }
}
15 голосов
/ 15 апреля 2010

ArrayList использует метод equals, реализованный в классе (ваш класс Thing для вашего случая), для сравнения.

11 голосов
/ 15 апреля 2010

Как правило, вы также должны переопределять hashCode() каждый раз, когда вы переопределяете equals(), даже если только для повышения производительности. HashCode() определяет, в какое «ведро» сортируется ваш объект при сравнении, поэтому любые два объекта, которые equal() оценивает как истинные, должны возвращать одинаковые hashCode value(). Я не могу вспомнить поведение по умолчанию hashCode() (если оно возвращает 0, тогда ваш код должен работать, но медленно, но если он возвращает адрес, то ваш код потерпит неудачу). Я помню много раз, когда мой код не удался, потому что я забыл переопределить hashCode(). :)

7 голосов
/ 15 апреля 2010

Использует метод equals для объектов. Поэтому, если переопределение Thing не равно и не использует переменные, хранящиеся в объектах для сравнения, оно не вернет true в методе contains().

5 голосов
/ 21 ноября 2013

Просто хотел заметить, что следующая реализация неверна, когда value не является примитивным типом:

public class Thing
{
    public Object value;  

    public Thing (Object x)
    {
        this.value = x;
    }

    @Override
    public boolean equals(Object object)
    {
        boolean sameSame = false;

        if (object != null && object instanceof Thing)
        {
            sameSame = this.value == ((Thing) object).value;
        }

        return sameSame;
    }
}

В этом случае я предлагаю следующее:

public class Thing {
    public Object value;  

    public Thing (Object x) {
        value = x;
    }

    @Override
    public boolean equals(Object object) {

        if (object != null && object instanceof Thing) {
            Thing thing = (Thing) object;
            if (value == null) {
                return (thing.value == null);
            }
            else {
                return value.equals(thing.value);
            }
        }

        return false;
    }
}
5 голосов
/ 10 сентября 2012
class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    equals (Thing x) {
        if (x.value == value) return true;
        return false;
    }
}

Вы должны написать:

class Thing {  
    public int value;  

    public Thing (int x) {
        value = x;
    }

    public boolean equals (Object o) {
    Thing x = (Thing) o;
        if (x.value == value) return true;
        return false;
    }
}

Теперь все работает;)

4 голосов
/ 15 апреля 2010

На других постерах был рассмотрен вопрос о том, как работает метод ().

Не менее важным аспектом вашего вопроса является правильная реализация equals (). И ответ на это действительно зависит от того, что составляет объектное равенство для этого конкретного класса. В приведенном вами примере, если у вас есть два разных объекта, каждый из которых имеет х = 5, они равны? Это действительно зависит от того, что вы пытаетесь сделать.

Если вас интересует только равенство объектов, то реализация по умолчанию *1006* для * .equals () (той, которая предоставляется Object) использует только идентификационные данные (то есть this == other). Если это то, что вы хотите, то просто не реализуйте equals () в вашем классе (пусть он наследуется от Object). Код, который вы написали, хотя и является правильным, если вы идете за идентичностью, никогда не появится в реальном классе, потому что он не дает никакой выгоды по сравнению с использованием реализации Object.equals () по умолчанию.

Если вы только начинаете заниматься этим, я настоятельно рекомендую книгу Джошуа Блоха «Эффективная Java». Это отличное чтение, и оно охватывает такие вещи (плюс, как правильно реализовать equals (), когда вы пытаетесь сделать больше, чем сравнение на основе идентичности)

2 голосов
/ 01 октября 2015

Ярлык из JavaDoc :

логическое содержит (Объект o)

Возвращает true, если этот список содержит указанный элемент. Более формально, возвращает true, если и только если этот список содержит хотя бы один элемент e такой что (o == null? e == null: o.equals (e))

...