我有一个名为Dish
的类,我在ArrayList
内处理它
所以我必须覆盖默认的hashCode()
方法。
@Override
public int hashCode() {
int hash =7;
hash = 3*hash + this.getId();
hash = 3*hash + this.getQuantity();
return hash;
}
当我得到两个包含id=4
,quan=3
和id=5
,quan=0
,hashCode()
的两道菜时,两者都相同;
((7*3)+4)*3+3 = 78
((7*3)+5)*3+0 = 78
我做错了什么?或者我选择的神奇数字7和3是错的?
如何正确覆盖hashCode()
以便生成唯一的哈希值?
PS :根据我从谷歌和搜索结果中搜索的内容,人们使用不同的数字但使用相同的方法。如果问题与数字有关,我如何明智地选择实际上并没有增加乘法成本的数字,同时对于更多数量的属性也能很好地工作。
假设我有7个int属性,而我的第二个魔法没有。是31,最后的哈希将是第一个魔术没有。 * 27512614111 即使我的所有属性都是0.那么我该怎么做呢没有我的哈希值数十亿,以免我的处理器负担-free?
答案 0 :(得分:4)
你可以使用这样的东西
public int hashCode() {
int result = 17;
result = 31 * result + getId();
result = 31 * result + getQuantity();
return result;
}
如果您的id对于每个对象都是唯一的,那么在计算哈希码时不需要使用数量。
以下是Joshua bloch的Effective Java摘录,讲述了如何实现hashcode方法
在名为result的int变量中存储一些常量非零值,例如17。
对于对象中的每个重要字段 f(通过equals方法考虑的每个字段),请执行以下操作:
一个。为字段计算int哈希码c:
i. If the field is a boolean, compute (f ? 1 : 0).
ii. If the field is a byte , char, short, or int, compute (int) f .
iii. If the field is a long , compute (int) (f ^ (f >>> 32)) .
iv. If the field is a float , compute Float.floatToIntBits(f) .
v. If the field is a double, compute Double.doubleToLongBits(f) , and then hash the resulting long as in step 2.a.iii.
vi. If the field is an object reference and this class’s equals method compares the field by recursively invoking equals, recursively invoke hashCode on the field. If a more complex comparison is required, compute a “canonical representation” for this field and invoke hashCode on the canonical representation. If the value of the field is null, return 0 (or some other constant, but 0 is traditional).
vii. If the field is an array, treat it as if each element were a separate field. That is, compute a hash code for each **significant element** by applying these rules recursively, and combine these values per step 2.b. If every element in an array field is significant, you can use one of the Arrays.hashCode methods added in release 1.5.
湾将步骤2.a中计算的哈希码c组合到结果中,如下所示: 结果= 31 *结果+ c;
返回结果。
编写完hashCode方法后,请问自己,相等的实例是否具有相同的哈希码。编写单元测试来验证你的直觉!如果相等的实例具有不相等的哈希码,找出原因并解决问题。
来源:Joshua Bloch的有效Java
答案 1 :(得分:2)
这完全没问题。散列函数不应该是普遍唯一的 - 它只是快速提示可能相等的元素,并且应该通过调用equals()来更深入地检查。
答案 2 :(得分:0)
从类的名称看起来数量是菜的数量。所以,有很多时候它有可能为零。我会说,如果getquantity()为零,请在散列函数中使用变量say x。这样:
@Override
public int hashCode() {
int hash =7;int x =0;
if(getQuantity==0)
{
x = getQuantity+getId();
}
else
{
x = getquantity;
}
hash = 3*hash + this.getId();
hash = 3*hash + x;
return hash;
}
我相信这应该减少hash的冲突。因为你拥有的getId()是一个唯一的数字。它也使x成为一个唯一的数字。