为异构密钥编写hashCode方法

时间:2010-09-21 07:54:59

标签: java performance hashcode

我有一个Java HashMap,它的键是java.lang.Object的实例,即:键是不同类型的。当两个不同类型的关键对象包含相同的变量值时,它们的hashCode值可能相同。

为了提高我的HashMap的get方法的性能,我倾向于将Java类型的名称混合到我的key对象的hashCode方法中。我没有在其他地方看过这个例子,所以我的这个可能是古怪的警报响起了。你认为将类型混合到hashCode是个好主意吗?我应该混合类名,还是相关Class对象的hashCode?

3 个答案:

答案 0 :(得分:3)

我不会混淆类型名称 - 但是如果你已经控制了hashCode算法,为什么不改变它以便它们不会冲突?例如,如果您使用常见的“加法和乘法”方法,则可以从不同的基本情况开始,或使用不同的乘数。

在您担心这个问题之前,您是否实际测量过真正与实际数据发生冲突的频率?这肯定是一个问题,还是你只关心可能是一个问题?

答案 1 :(得分:1)

我认为当你决定拥有不同类型的钥匙时,这个可能是古怪的警报应该已经消失了。但是我们假设这是一个实际上可以使用Object的情况。

如果您发现此特定查找被确定为系统中的热点,则应该在不混合类型名称的情况下尝试并对性能进行压力测试。表现可能无关紧要。

与Jon暗示的一样,哈希映射的性能通过减少冲突得到改善。在类型名称中混合就像增加冲突一样可能会减少冲突。为了使您的散列图保持在峰值状态,您希望任何特定散列码的可能性与有效键值域中的任何其他散列码的可能性大致相同。因此,哈希码10的概率应与100或任何其他数的概率大致相同。这样哈希表桶就可以均匀填充(很可能)。所以无论你有A型或B型的对象都无所谓。只是所有出现的键值的哈希码的概率分布。

答案 2 :(得分:0)

多年以后......

除了它是一个过早的优化,它不是一个坏主意,而且开销很小。 Choy首先建议的建议肯定是好的,但有时简单的优化比分析花费的时间少得多。这似乎就是这种情况。

我使用了已建议的不同乘数,并将其混合在getClass().getHashCode()中。

或者getClass().getName().getHashCode()因为它在JVM调用中保持一致,如果您想要一个可重现的HashMap迭代顺序以便于调试,这可能会有所帮助。请注意,您永远不应该依赖于这样的可重复性,并且有很多东西会破坏它。