在我最近的一个问题中,我被告知我需要覆盖我的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
中的任何其他变量?如果我没有正确实施这些方法,我该如何更改/改进它们?
答案 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();
}