Java 我是否正确重写了equals和hashcode?

Java 我是否正确重写了equals和hashcode?,java,overriding,equals,hashcode,Java,Overriding,Equals,Hashcode,在我最近的问题中,我被告知我需要重写我的equals和hashcode方法(以及其他方法)。因此,我花了一些时间阅读了几篇文章,并试图提出一个适当的实现 以下是我读到的一些文章: 所有的文章都很好。由于这是我第一次尝试这样做,我只想确保我没有犯一些简单(或愚蠢)的错误 我将使用name来指示我的Person对象是否等同于另一个Person对象。原因是,所有其他变量都可能不同,但名称始终是唯一的 更新以反映建议的更改 public class Person { private

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

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

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

我将使用
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();
    }
}
我的问题如下:

  • 我是否正确地实现了这些方法
  • 由于
    name
    是唯一确定唯一性的变量,我是否需要检查
    hashcode
    中的任何其他变量
  • 我在StackOverflow上读到,不久前31被选为一个好的素数,但现在选择一个更大的素数更好?有人能证实或否认这一说法吗?(索赔是在上面的第三个链接中提出的)
  • 如果我没有正确地实现这些方法,如何更改/改进它们?

    equals()
    中:

    缺少
    false
    ,您可以:

    // Both are Person instances, no need to use the accessor here
    return name.equals(p.name);
    
    至于
    hashCode()
    ,只需
    返回name.hashCode()

    此外,名称可以为空吗?你的方法似乎不能解释这一点。(编辑:答案:否)

    关于你的问题:

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

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

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

    这个,不知道

    为了更全面地了解
    .equals()
    /
    .hashCode()
    合同,我将提到一个来自Guava的实用程序类:。此抽象类对于给定对象的实现 类可以让您创建
    s,从而
    映射
    s,将这些对象作为成员(键),就好像它们对这两个函数有不同的实现:

    Equivalence<MyClass> eq = ....;
    
    Set<Equivalence.Wrapper<MyClass>> set = ...;
    
    set.add(eq.wrap(myClassInstance));
    
    等效等式=。。。。;
    集合=。。。;
    set.add(eq.wrap(myClassInstance));
    
    这实际上在某些情况下非常有用…

    equals()
    中:

    缺少
    false
    ,您可以:

    // Both are Person instances, no need to use the accessor here
    return name.equals(p.name);
    
    至于
    hashCode()
    ,只需
    返回name.hashCode()

    此外,名称可以为空吗?你的方法似乎不能解释这一点。(编辑:答案:否)

    关于你的问题:

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

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

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

    这个,不知道

    为了更全面地了解
    .equals()
    /
    .hashCode()
    合同,我将提到一个来自Guava的实用程序类:。此抽象类对于给定对象的实现 类可以让您创建
    s,从而
    映射
    s,将这些对象作为成员(键),就好像它们对这两个函数有不同的实现:

    Equivalence<MyClass> eq = ....;
    
    Set<Equivalence.Wrapper<MyClass>> set = ...;
    
    set.add(eq.wrap(myClassInstance));
    
    等效等式=。。。。;
    集合=。。。;
    set.add(eq.wrap(myClassInstance));
    

    这在某些情况下非常有用…

    您的
    equals
    在所有情况下都需要返回一个值,只需更改结尾部分以返回
    名称。equals

    @Override
    public boolean equals(Object o) {
        ...
        return name.equals(o.getName());
    }
    
    此外,您的hashcode实际上是有害的,它所做的只是使用
    name.hashcode()
    ,然后将其乘以31,最好直接使用名称中的默认Java字符串hashcode

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

    您的
    equals
    在所有情况下都需要返回一个值,只需更改结束部分以返回
    名称。equals

    @Override
    public boolean equals(Object o) {
        ...
        return name.equals(o.getName());
    }
    
    此外,您的hashcode实际上是有害的,它所做的只是使用
    name.hashcode()
    ,然后将其乘以31,最好直接使用名称中的默认Java字符串hashcode

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

    很好,不,名称不能为空。谢谢你的快速回复!我将进行这些修复请注意对
    .equals()
    的编辑:使用
    o
    访问
    name
    时无需使用访问器。另一件事:
    Person
    可以扩展吗?谢谢,我注意到了您(以及greedybuddha)所做的更改,并将在编辑该类时对其进行检查。暂不延长
    Person
    的有效期。不过,我也没有计划在将来扩展它。遗憾的是,您也有setter,否则我建议将实例变量
    final
    。或者你可以使用一个构建器来构建
    Person
    对象,这将允许该类是不可变的,这是一个很好的加号。谢谢你的快速回复!我将进行这些修复注意编辑
    .equals()
    :无需使用访问者通过
    o
    访问
    name
    。另一件事:
    Person
    可以扩展吗?谢谢,我注意到了您(以及greedybuddha)所做的更改,并将在我进行edi时对其进行检查