唯一的原因是避免将值聚集到少量的存储桶中(是的,分布)。更均匀的分布式哈希表将执行更一致的性能。
来自http://srinvis.blogspot.com/2006/07/hash-table-lengths-and-prime-numbers.html
如果假设您的hashCode函数在{x,2x,3x,4x,5x,6x...}中产生以下hashCodes,那么所有这些都将聚集在m个buckets中,其中m=bucket x)。(验证/派生这一点很简单)。现在,您可以执行以下操作之一来避免集群
确保您不会生成太多的hashCodes,它们是另一个hashCode的倍数,例如{x,2x,3x,4x,5x,6x...}.But如果您的hashTable应该有数百万个条目,这可能会有些困难。
或简单地通过使table_length (GreatestCommonFactor,x)等于1来使m等于table_length,即通过使table_length与x互质。如果x可以是任意数字,则确保table_length是质数。
更新:(来自原始答案作者)
这个答案对于哈希表的常见实现是正确的,包括原始Hashtable的Java实现以及.NET的Dictionary的当前实现。
然而,对于Java语言的HashMap,容量应该是质数的答案和假设都是不准确的。HashMap的实现非常不同,它使用一个基数为2的表来存储存储桶,并使用n-1 & hash来计算使用哪个存储桶,而不是使用更传统的hash % n公式。
Java的HashMap将强制实际使用的容量是请求容量之上的下一个最大的基数2。
比较Hashtable
代码语言:javascript复制int index = (hash & 0x7FFFFFFF) % tab.lengthhttps://github.com/openjdk/jdk/blob/jdk8-b120/jdk/src/share/classes/java/util/Hashtable.java#L364
转到HashMap
代码语言:javascript复制first = tab[(n - 1) & hash]https://github.com/openjdk/jdk/blob/jdk8-b120/jdk/src/share/classes/java/util/HashMap.java#L569