良好的 hashCode() 实现 [英] Good hashCode() Implementation

查看:24
本文介绍了良好的 hashCode() 实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

hashCode 方法的最佳实现 中接受的答案提供了一种看似不错的查找哈希码的方法.但我是哈希码的新手,所以我不太知道该怎么做.

对于 1),我选择什么非零值有关系吗?1 是否与质数 31 等其他数字一样好?

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

<小时>

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

public MyClass{长 a, b, c;//这些是唯一的字段//一些代码和方法公共 int hashCode(){返回 37 * (37 * ((int) (a ^ (a >> 32))) + (int) (b ^ (b >> > 32)))+(int)(c^(c>>>32));}}

解决方案

  1. 价值并不重要,它可以是您想要的任何东西.质数将导致 hashCode 值的更好分布,因此它们是首选.
  2. 您不必添加它们,您可以自由实现您想要的任何算法,只要它满足 hashCode 合同:

<块引用>

  • 在 Java 应用程序执行期间,只要在同一个对象上多次调用它,hashCode 方法必须始终返回相同的整数,前提是在对象的 equals 比较中没有使用任何信息修改的.该整数不需要从应用程序的一次执行到同一应用程序的另一次执行保持一致.
  • 如果两个对象根据 equals(Object) 方法相等,则对这两个对象中的每一个调用 hashCode 方法必须产生相同的整数结果.
  • 如果两个对象根据 equals(java.lang.Object) 方法不相等,则不需要对这两个对象中的每一个调用 hashCode 方法必须产生不同的整数结果.但是,程序员应该意识到,为不相等的对象生成不同的整数结果可能会提高哈希表的性能.

有些算法可以被认为是不好的hashCode 实现,简单地添加属性值就是其中之一.原因是,如果你有一个有两个字段的类,Integer a, Integer b 和您的 hashCode() 只是总结了这些值,然后 hashCode 值的分布高度依赖于您的实例存储的值.例如,如果 a 的大部分值在 0-10 之间,而 b 的大部分值在 0-10 之间,则 hashCode 值在0-20.这意味着如果您将此类的实例存储在例如HashMap 多个实例将被存储在同一个桶中(因为许多具有不同 ab 值但具有相同总和的实例将被放入其中同一个桶).这将对地图上的操作性能产生不利影响,因为在查找时,将使用 equals() 比较存储桶中的所有元素.

关于算法,它看起来不错,它与 Eclipse 生成的算法非常相似,但它使用的是不同的素数,31 不是 37:

@Override公共 int hashCode() {最终 int 素数 = 31;整数结果 = 1;结果 = 素数 * 结果 + (int) (a ^ (a >> > 32));结果 = 素数 * 结果 + (int) (b ^ (b >> > 32));结果 = 素数 * 结果 + (int) (c ^ (c >> > 32));返回结果;}

The accepted answer in Best implementation for hashCode method gives a seemingly good method for finding Hash Codes. But I'm new to Hash Codes, so I don't quite know what to do.

For 1), does it matter what nonzero value I choose? Is 1 just as good as other numbers such as the prime 31?

For 2), do I add each value to c? What if I have two fields that are both a long, int, double, etc?


Did I interpret it right in this class:

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));
    }
}

解决方案

  1. The value is not important, it can be whatever you want. Prime numbers will result in a better distribution of the hashCode values therefore they are preferred.
  2. You do not necessary have to add them, you are free to implement whatever algorithm you want, as long as it fulfills the hashCode contract:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

There are some algorithms which can be considered as not good hashCode implementations, simple adding of the attributes values being one of them. The reason for that is, if you have a class which has two fields, Integer a, Integer b and your hashCode() just sums up these values then the distribution of the hashCode values is highly depended on the values your instances store. For example, if most of the values of a are between 0-10 and b are between 0-10 then the hashCode values are be between 0-20. This implies that if you store the instance of this class in e.g. HashMap numerous instances will be stored in the same bucket (because numerous instances with different a and b values but with the same sum will be put inside the same bucket). This will have bad impact on the performance of the operations on the map, because when doing a lookup all the elements from the bucket will be compared using equals().

Regarding the algorithm, it looks fine, it is very similar to the one that Eclipse generates, but it is using a different prime number, 31 not 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;
}

这篇关于良好的 hashCode() 实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆