我是否正确地重写了等号和hashcode ?



在我最近的问题中,我被告知我需要覆盖我的equalshashcode方法(以及其他事情)。因此,我花了一些时间阅读了一些文章,并试图提出一个适当的实现。

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

  • 维基百科的哈希码
  • StackOverflow重写等号和hashcode
  • 为什么hashcode使用乘数31

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

我将使用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被选为一个很好的素数,但是现在选择一个更大的素数更好吗?有人能证实或否认这种说法吗?(该声明在上面的第三个链接中提出)

如果我没有正确地实现这些方法,我如何改变/改进它们?

In 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();

name可以为空吗?你的方法似乎不能解释这一点。(编辑:答案:no)

关于你的问题:

既然name是唯一决定唯一性的变量,我还需要检查hashcode中的其他变量吗?

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

我在StackOverflow上读到31被选为一个很好的素数,但是现在选择一个更大的素数更好吗?有人能证实或否认这种说法吗?(在上面的第三个链接中提出了索赔)

这个,不知道…

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

Equivalence<MyClass> eq = ....;
Set<Equivalence.Wrapper<MyClass>> set = ...;
set.add(eq.wrap(myClassInstance));

在某些情况下,非常有用。

您的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();
}

相关内容

最新更新