Как метод ArrayList содержит() метод оценки объектов?

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

Ответ 1

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

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

Ответ 2

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

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;
    }
}

Ответ 3

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

Ответ 4

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

Ответ 5

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

Ответ 6

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;
    }
}

Теперь он работает;)

Ответ 7

Другие плакаты рассмотрели вопрос о том, как contains() работает.

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

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

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

Ответ 8

Просто хотелось заметить, что следующая реализация неверна, если 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;
    }
}

Ответ 9

Ярлык из JavaDoc:

boolean содержит (Object o)

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