好hashCode()实现

Jus*_*tin 9 java hash

hashCode方法的Best实现中接受的答案给出了一种看似很好的方法来查找哈希码.但我是Hash Codes的新手,所以我不知道该怎么做.

对于1),我选择的非零值是否重要?是1就像其他号码如黄金一样好31

对于2),我是否将每个值添加到c?如果我有两个字段都是一个long,int,double,等?


我是否在本课程中正确解释了它:

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

Ada*_*ion 16

  1. 价值并不重要,它可以是你想要的任何东西.素数将导致hashCode值的更好分布,因此它们是首选.
  2. 您没有必要添加它们,只要它符合hashCode 合同,您就可以自由地实现您想要的任何算法:
  • 每当在执行Java应用程序期间多次在同一对象上调用它时,该hashCode方法必须始终返回相同的整数,前提是不修改对象的等比较中使用的信息.从应用程序的一次执行到同一应用程序的另一次执行,该整数不需要保持一致.
  • 如果根据equals(Object)方法两个对象相等,则hashCode在两个对象中的每一个上调用方法必须产生相同的整数结果.
  • 如果两个对象根据equals(java.lang.Object)方法不相等则不是必需的,则在两个对象中的每一个上调用hashCode方法必须产生不同的整数结果.但是,程序员应该知道为不等对象生成不同的整数结果可能会提高哈希表的性能.

有些算法可以被认为是不好的hashCode实现,简单地添加属性值就是其中之一.原因是,如果你有一个有两个字段的类,Integer a,Integer b和你hashCode()刚刚总结这些值,那么值的分布在hashCode很大程度上取决于你的实例存储的值.例如,如果大部分的值的一个是0-10之间b是0-10之间,然后将该hashCode值是0-20之间.这意味着如果您将此类的实例存储在例如HashMap多个实例中,则将存储在同一个存储桶中(因为具有不同ab值但具有相同总和的多个实例将被放在同一个存储桶中).这将对地图上的操作性能产生不良影响,因为在进行查找时,将使用桶中的所有元素进行比较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;
}
Run Code Online (Sandbox Code Playgroud)


Boh*_*ian 5

对于长值,已经存在表现良好的哈希码方法 - 不要重新发明轮子:

int hashCode = Long.valueOf((a * 31 + b) * 31 + c).hashCode();
Run Code Online (Sandbox Code Playgroud)

乘以素数(通常在JDK类中为31)并累加总和是从多个数字创建"唯一"数字的常用方法.

Long的hashCode()方法使结果在整个int范围内正确分布,使得哈希"表现良好"(基本上是伪随机的).

  • @gangqinlaohu不知道,但我不必知道.我可以保证哈希的JDK代码比你提出的任何东西都要好.这些课程经过严格的测试和研究.此外,阅读我的代码比你的更容易.仅此一点很有价值.B)我相信在最后散列会更好(而且它的代码更少)但我会接受单个散列的组合(可能只是添加). (4认同)