假设我创建了一个对象并将其添加到数组列表中。如果我然后用完全相同的构造函数输入创建另一个对象,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;
    }
}

这是类应该如何实现有contains()返回true吗?


当前回答

其他帖子已经解决了contains()如何工作的问题。

您的问题中同样重要的一个方面是如何正确地实现equals()。这个问题的答案取决于这个特定类的对象相等的构成。在你提供的例子中,如果你有两个x=5的不同对象,它们相等吗?这真的取决于你想要做什么。

如果你只对对象的相等性感兴趣,那么.equals()的默认实现(由object提供的)只使用标识符(即this == other)。如果这是你想要的,那么就不要在你的类上实现equals()(让它从Object继承)。你写的代码,虽然是正确的,如果你是为了标识,永远不会出现在一个真正的类b/c,它提供没有使用默认的Object.equals()实现的好处。

如果您刚刚开始学习这些东西,我强烈推荐Joshua Bloch的《Effective Java》一书。这是一本很棒的读物,涵盖了这类内容(以及当您试图做更多基于标识的比较时如何正确实现equals())

其他回答

ArrayList使用在类(你的case Thing类)中实现的equals方法来进行相等比较。

Generally you should also override hashCode() each time you override equals(), even if just for the performance boost. HashCode() decides which 'bucket' your object gets sorted into when doing a comparison, so any two objects which equal() evaluates to true should return the same hashCode value(). I cannot remember the default behavior of hashCode() (if it returns 0 then your code should work but slowly, but if it returns the address then your code will fail). I do remember a bunch of times when my code failed because I forgot to override hashCode() though. :)

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

现在它工作了;)

只是想指出,当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;
    }
}

其他帖子已经解决了contains()如何工作的问题。

您的问题中同样重要的一个方面是如何正确地实现equals()。这个问题的答案取决于这个特定类的对象相等的构成。在你提供的例子中,如果你有两个x=5的不同对象,它们相等吗?这真的取决于你想要做什么。

如果你只对对象的相等性感兴趣,那么.equals()的默认实现(由object提供的)只使用标识符(即this == other)。如果这是你想要的,那么就不要在你的类上实现equals()(让它从Object继承)。你写的代码,虽然是正确的,如果你是为了标识,永远不会出现在一个真正的类b/c,它提供没有使用默认的Object.equals()实现的好处。

如果您刚刚开始学习这些东西,我强烈推荐Joshua Bloch的《Effective Java》一书。这是一本很棒的读物,涵盖了这类内容(以及当您试图做更多基于标识的比较时如何正确实现equals())