0

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

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

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

我将使用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 回答 2

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

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

至于你的问题:

由于 name 是唯一决定唯一性的变量,我是否需要检查哈希码中的任何其他变量?

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

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

这个,不知道...

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

Equivalence<MyClass> eq = ....;

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

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

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

于 2013-06-06T18:47:48.230 回答
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();
}
于 2013-06-06T18:48:45.527 回答