整数 hashCode 的最佳实现是啥?

Posted

技术标签:

【中文标题】整数 hashCode 的最佳实现是啥?【英文标题】:What is the best implementation of hashCode of an integer?整数 hashCode 的最佳实现是什么? 【发布时间】:2015-11-12 13:13:51 【问题描述】:

我创建了一些用于 hashTable 的整数的 hashCode 实现,但它们似乎都没有至少接近均匀分布。那么假设 hashTable 的大小接近一百并且整数大到几千的数量级,那么整数的 hashCode 的最佳实现是什么?提前致谢。

【问题讨论】:

为什么不直接使用整数本身作为自己的哈希? 如果您的源整数分布良好,您可以应用% 100 作为哈希码 由于 32 位整数集本身是均匀分布的,我假设您有一个特定的整数子集可以使用,但事实并非如此。因此,您需要考虑对特定数据及其实际分布的约束,以便设计一个均匀分布该子集的哈希码。您没有在问题中提供该信息。 @AaronD 这会导致 hashTable 的大小变大......即使我采用 hashCode%hashTableSize,对于接近于 10 的数字(即 hashTableSize)也无法正常工作 @RealSkeptic 我正在为 hashTable 实现 hashCode。如果 hashCodes 集中,则 hashTable 将不会有效。 【参考方案1】:

我建议“最好”的实现,不管这意味着什么,几乎可以肯定

Integer.valueOf(value).hashCode()

【讨论】:

并且,根据Java docs,IntegerhashCode()方法返回Integer所代表的原始int值。 嗯...我认为通用 解决方案不一定是最好的。事实上,优化在于具体化而不是泛化。【参考方案2】:

由于你的哈希表比较小,模函数是最简单的实现,如果输入数字是随机的,分布也应该是随机的。

public int hashCode(int x)
   return x%tableSize;

如here 所述,更好的实现是使用乘法。

(x*someNumber) % table size;

here 描述了其他散列函数,请查看它们。 希望这会有所帮助。

【讨论】:

【参考方案3】:

如果您的数据的键是均匀分布的,则不仅仅是使用整数本身作为键。如果您的密钥不是均匀分布的,您需要修改整数,使其在所有整数的频谱中分布得更均匀。如何做到这一点取决于您的密钥是如何分布的以及确切的 Map 实现。

您确定您没有进行过早优化吗?在只有 100 个条目的 Map 中,如果您有恒定的查找时间(完美分布)或线性查找时间(每个条目都有键冲突),这实际上并不重要。迭代 100 个项目是如此之快,在基准测试之外,您很可能不会注意到差异。如果一个列表的平均速度甚至不比具有如此小的数据集的地图更快,那么进行基准测试会很有趣。

【讨论】:

【参考方案4】:

因此,您在 X 轴上有 数千个 值,并且您想在 Y 轴上将它们“转换”成更小的范围,数百。显然,您可以除以 10 或获得模数,但您还希望在目标范围内尽可能均匀地分布它们。

我猜你需要一个压缩函数。

例如,您可以将 sine 函数应用于输入并乘以哈希表的大小。期间应该有什么值?这取决于:您期望输入值越接近,周期越高(因此非常接近的两个值会产生两个非常不同的结果)。反之亦然:如果预计输入值不会非常接近,则可以使用一小段时间。

private int hashCode(int input, int tableSize)

    return (int)(tableSize*Math.sin(PERIOD*input));

【讨论】:

【参考方案5】:

来自 MurmurHash3 的终结雪崩函数:

int h = key;
h ^= h >>> 16;
h *= 0x85ebca6b;
h ^= h >>> 13;
h *= 0xc2b2ae35;
h ^= h >>> 16;

【讨论】:

以上是关于整数 hashCode 的最佳实现是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Java中的“内部地址”是啥?

HashCode计算

集合的 hashCode 方法的最佳实现

hashCode花式卖萌

为 SQL Redshift 连接两个整数的最佳方法是啥?

由于 Objective-C 中的整数溢出,处理和报告内存分配错误的最佳方法是啥?