【发布时间】:2012-04-03 12:52:07
【问题描述】:
我用 Java 生成了一堆对象。每个对象都有属性 area 和一组整数。例如,我想将这些对象存储在地图中(键应该是按递增顺序排列的整数)。如果两个对象的面积相等且集合相同,则两个对象是相同的。
如果两个对象的面积不同,我就不需要检查它们的集合是否相同。
在 Java 中实现这一点的最佳实践是什么?我应该如何组合散列和相等函数?
【问题讨论】:
我用 Java 生成了一堆对象。每个对象都有属性 area 和一组整数。例如,我想将这些对象存储在地图中(键应该是按递增顺序排列的整数)。如果两个对象的面积相等且集合相同,则两个对象是相同的。
如果两个对象的面积不同,我就不需要检查它们的集合是否相同。
在 Java 中实现这一点的最佳实践是什么?我应该如何组合散列和相等函数?
【问题讨论】:
这是由 IDE 生成的 hashCode\equals 示例对:
class Sample {
final int area;
final Set<Integer> someData;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Sample sample = (Sample) o;
if (area != sample.area) return false;
if (!someData.equals(sample.someData)) return false;
return true;
}
@Override
public int hashCode() {
int result = area;
result = 31 * result + someData.hashCode();
return result;
}
}
此代码假定someData 不能为空——以简化操作。您可以看到首先检查类型的相等性,然后检查area 的相等性,然后检查Set<Integer> 的相等性。请注意,在此使用了 Set 的内置 equals - 因此您可以重复使用该方法。这是测试复合类型是否相等的惯用方法。
【讨论】:
只需在equals 中首先比较它们的区域(当然在== 和类型检查之后),如果它们不同,则返回false。如果面积相等,继续比较集合。
对于一般实现equals(和hashCode),这里是a relevant thread和a good article(包括几个进一步的参考)。
【讨论】:
经验法则是,您应该比较 equals() 实现中的所有相关字段(首先是最快的,因此先比较您的 areas,然后是整数集)并在您的 hashCode() 中使用相同的字段.如果有疑问,请使用 Eclipse 的 Source - Generate hashCode() and equals()... 功能(然后修复 equals() 代码以首先比较 areas。)
【讨论】: