Good hashCode()实现

问题描述 投票:9回答:2

Best implementation for hashCode method中的可接受答案为查找哈希码提供了一种看似不错的方法。但是我是哈希代码的新手,所以我不太了解该怎么做。

对于1),我选择哪个非零值有关系吗? 1是否与其他数字(例如质数31)一样好?

对于2),是否将每个值添加到c?如果我同时具有两个字段longintdouble等怎么办?


我在这堂课中解释得对吗:

public MyClass{
    long a, b, c; // these are the only fields
    //some code and methods
    public int hashCode(){
        return 37 * (37 * ((int) (a ^ (a >>> 32))) + (int) (b ^ (b >>> 32))) 
                 + (int) (c ^ (c >>> 32));
    }
}
java hash
2个回答
16
投票
  1. 该值并不重要,它可以是您想要的任何值。质数将导致hashCode值的更好分布,因此首选。
  2. 您不必添加它们,只要满足hashCode contract,您就可以自由地实现所需的任何算法:
  • [在Java应用程序执行期间,在同一对象上多次调用它时,hashCode方法必须一致地返回相同的整数,只要没有修改该对象的equals比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,此整数不必保持一致。
  • 如果根据equals(Object)方法两个对象相等,则在两个对象中的每个对象上调用hashCode方法必须产生相同的整数结果。
  • [如果根据equals(java.lang.Object)方法,两个对象不相等,则不需要,那么在两个对象中的每个对象上调用hashCode方法必须产生不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能。

[有些算法可以被认为是不好的hashCode实现,简单添加属性值就是其中之一。这样做的原因是,如果您有一个包含两个字段的类,Integer aInteger b,而您的hashCode()只是对这些值求和,则hashCode的分布]值高度取决于实例存储的值。例如,如果a的大多数值在0-10之间,并且b的大多数值在0-10之间,则hashCode值在0-20之间。这意味着如果您将此类的实例存储在例如HashMap许多实例将存储在同一存储桶中(因为许多具有不同[b值但具有相同总和的实例将放入同一存储桶中)。这将对地图上的操作性能产生不良影响,因为进行查找时,将使用equals()比较存储桶中的所有元素。关于算法,它看起来不错,它与Eclipse生成的算法非常相似,但是它使用了不同的质数,而不是31:37。

@Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (int) (a ^ (a >>> 32)); result = prime * result + (int) (b ^ (b >>> 32)); result = prime * result + (int) (c ^ (c >>> 32)); return result; }


5
投票
行为良好的哈希码方法对于长值已经存在-不要重新发明轮子:

0
投票
与1和31相乘之间有很大差异。
© www.soinside.com 2019 - 2024. All rights reserved.