我是否正确覆盖了equals和hashcode?

时间:2013-06-06 18:46:03

标签: java override equals hashcode

在我最近的一个问题中,我被告知我需要覆盖我的equalshashcode方法(以及其他方面)。所以我花了一点时间阅读一些文章并尝试提出正确的实现。

以下是我读过的一些文章:

所有文章都很好。由于这是我第一次尝试这样做,我只是想确定我没有犯一些简单(或愚蠢)的错误。

我将使用name来指示我的Person对象是否等同于另一个Person对象。原因是所有其他变量都可以变化,但名称将始终是唯一的。

已更新以反映建议的更改

public class Person {

    private String name;
    private int p_number;
    private String address;
    //other variables

    public Person(String a_name) {
        name = a_name;
    }

    public String getName() {
        return name;
    }

    //other getters and setters

    @Override
    public boolean equals(Object o) {
        if(o == null) 
            return false;

        if(o == this) 
            return true;

        if(!(o instanceof Person)) 
            return false;

        Person p = (Person) o;
        return name.equals(p.name));

    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }
}

我的问题如下:

  1. 我是否正确实施了这些方法?
  2. 由于name是唯一确定唯一性的变量,我是否需要费心检查hashcode中的任何其他变量?
  3. 我正在读StackOverflow,31年前被选为一个很好的素数,但现在选择更大的素数更好?有人可以确认或否认这种说法吗? (索赔是在上面的第三个链接中提出的)
  4. 如果我没有正确实施这些方法,我该如何更改/改进它们?

2 个答案:

答案 0 :(得分:3)

equals()

if(name.equals(p.getName()))
    return true;

缺少false,您可以:

// Both are Person instances, no need to use the accessor here
return name.equals(p.name);

关于hashCode(),只需return name.hashCode();

另外,名字可以为null吗?你的方法似乎没有考虑到这一点。 (编辑:回答:否)

关于你的问题:

  

由于name是唯一确定唯一性的变量,我是否需要打扰检查hashcode中的任何其他变量?

不,当然不是!如果你的名字相同但年龄不同,这会导致相同的对象的哈希代码不同,这违反了Object合同!

  

我正在阅读StackOverflow,31之前被选为一个很好的素数,但现在选择更大的素数更好?有人可以确认或否认这种说法吗? (索赔是在上面的第三个链接中提出的)

这个,不知道......

为了更完整地了解.equals() / .hashCode()合同,我将提到Guava的实用程序类:Equivalence。给定的这个抽象类的实现 class可以允许您创建Set s,因此Map s,将这些对象作为成员(键),就像它们具有以下两个函数的不同实现一样:

Equivalence<MyClass> eq = ....;

Set<Equivalence.Wrapper<MyClass>> set = ...;

set.add(eq.wrap(myClassInstance));

在某些情况下,实际上非常非常有用......

答案 1 :(得分:1)

您的equals需要在所有情况下都返回一个值,只需更改结束部分即可返回name.equals

@Override
public boolean equals(Object o) {
    ...
    return name.equals(o.getName());
}

此外,您的哈希码实际上是有害的,只需使用name.hashCode(),然后将其乘以31,最好直接使用名称中的默认Java字符串哈希码。

@Override
public int hashCode() {
    return name.hashCode();
}