Tom*_*Tom 33 java equals hashcode
我定义了两个类,它们都包含对另一个对象的引用.它们看起来与此类似(这是简化的;在我的真实域模型中,A类包含B的列表,每个B都有一个返回父A的引用):
public class A {
public B b;
public String bKey;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((b == null) ? 0 : b.hashCode());
result = prime * result + ((bKey == null) ? 0 : bKey.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof A))
return false;
A other = (A) obj;
if (b == null) {
if (other.b != null)
return false;
} else if (!b.equals(other.b))
return false;
if (bKey == null) {
if (other.bKey != null)
return false;
} else if (!bKey.equals(other.bKey))
return false;
return true;
}
}
public class B {
public A a;
public String aKey;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((a == null) ? 0 : a.hashCode());
result = prime * result + ((aKey == null) ? 0 : aKey.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof B))
return false;
B other = (B) obj;
if (a == null) {
if (other.a != null)
return false;
} else if (!a.equals(other.a))
return false;
if (aKey == null) {
if (other.aKey != null)
return false;
} else if (!aKey.equals(other.aKey))
return false;
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
在hashCode与equals已通过使用Eclipse中A和B这两个问题的两个场产生的是调用equals或hashCode在任一对象方法的结果在StackOverflowError因为它们都调用另一个对象的equals和hashCode方法.例如,StackOverflowError使用上述对象时,以下程序将失败:
public static void main(String[] args) {
A a = new A();
B b = new B();
a.b = b;
b.a = a;
A a1 = new A();
B b1 = new B();
a1.b = b1;
b1.a = a1;
System.out.println(a.equals(a1));
}
Run Code Online (Sandbox Code Playgroud)
如果以这种方式使用循环关系定义域模型存在固有的错误,请告诉我.据我所知虽然这是一个相当常见的情况,对吗?
定义hashCode和equals在这种情况下,最佳做法是什么?我想保留equals方法中的所有字段,以便它是对象的真正深度相等比较,但我不知道如何解决这个问题.谢谢!
我同意I82Much的,你应该避免乙引用它们的父注释:这是信息重复,这通常只会导致麻烦,但你可能需要在你的情况下这样做.
即使你离开父参考B,尽可能的散列码而言,你应该完全忽略父参考,并只使用真正的内部变量B来构建哈希码.
该As为只是容器,其价值是由它们的内容,这是包含的值完全确定B,依次类推应他们的哈希键.
如果A是无序集,则必须非常小心,您根据B值(或B哈希码)构建的哈希代码不依赖于某些排序.例如,如果通过B在某个序列中添加和乘以所包含的哈希码来构建哈希码,则应首先在计算求和/乘法的结果之前通过递增顺序来对哈希码进行排序.同样,A.equals(o)不得依赖于Bs 的排序(如果是无序集).
请注意,如果您使用的是java.util.Collection内A,那么就固定B忽略父参考会自动给出有效的S哈希码A的散列码,因为CollectionS按默认(订货与否)具有良好的散列码.