[英]Hashcode & equals implementation
我正在编写一些代码来演示equals和hashcode,对于我的实现,我使用了User示例:
public class User {
private String name;
private String pass;
//...
@Override
public boolean equals(Object obj) {
if (obj == null) { return false; }
if (obj == this) { return true; }
if (obj.getClass() != this.getClass()) {
return false;
}
User rhs = (User) obj;
EqualsBuilder eb = new EqualsBuilder();
eb.append(this.getName(), rhs.getName());
//eb.append(this.getPass(), rhs.getPass());
return eb.isEquals();
}
@Override
public int hashCode() {
HashCodeBuilder hcb = new HashCodeBuilder(17, 37);
hcb.append(this.getName());
hcb.append(this.getPass());
return hcb.toHashCode();
}
//...
public static void main(String[] args) {
User u1 = new User("foo","foo1");
User u2 = new User("bar","bar1");
System.out.println(u1.equals(u2));
System.out.println(u1.hashCode() + " ?= " + u2.hashCode());
User u3 = new User("foo","foo1");
User u4 = new User("foo","bar1");
System.out.println(u3.equals(u4));
System.out.println(u3.hashCode() + " ?= " + u4.hashCode());
}
}
输出:
false
2128613651 ?= 2129111967
true
2128615478 ?= 2214545177
我想我做错了,因为我的对象现在可以相等但具有不同的哈希码(我知道这很糟糕),但是我想仅当用户名也相等时才使用户相等。名称AND通行证等于。
我如何才能遵守这些约定,并实现自己的目标? 感谢您的帮助/说明:)
一般而言,如果equals()
方法中不存在字段,则不应在hashCode()
方法中引用该字段。
这样可以确保您的hashcode()
结果不会比equals()
结果更频繁地更改。 考虑将您的方法更改为:
@Override
public int hashCode() {
HashCodeBuilder hcb = new HashCodeBuilder(17, 37);
hcb.append(this.getName());
return hcb.toHashCode();
}
话虽如此,创建一个非直觉的equals()
方法很少是一个好主意。 我自然会假设您的方法也将考虑密码,因为您将来的许多维护者也会考虑。 如果不进行真正的相等性测试,则单元测试可能很难编写。 考虑创建自己的方法是否更好,例如
public boolean usernameEquals(User other) {
...
}
所有相等的对象具有相同的哈希码。 但并非所有具有相同哈希码的对象都是相等的。
您在hascode方法中使用的所有字段都应在equals方法中使用。
我不会说你做错了。 就合同而言, 如果2个对象相等,则它们应具有相同的hashCode。 如果2个对象具有相同的hashCode,则它们不必相等
如果将2个User实例的相等性定义为- 它们相等,则如果它们的名称相等 ,那么您就可以了。 就hashCodes而言,您是对的,因为如果2个对象的hashCodes不相等,则这些对象也不相等。
BTW Duncan完全正确地指出, 创建非直观的equals()方法很少是一个好主意
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.