整数 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,Integer
的hashCode()
方法返回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 的最佳实现是啥?的主要内容,如果未能解决你的问题,请参考以下文章