Java:一个“素数”还是一个“二的幂”作为HashMap大小?
许多书籍和教程都说,哈希表的大小必须是均匀分布所有存储桶中的键的素数。但是Java总是使用一个2的幂的大小。它不应该使用素数吗?更好的是,“素数”或“两个幂”作为哈希表大小?HashMap
许多书籍和教程都说,哈希表的大小必须是均匀分布所有存储桶中的键的素数。但是Java总是使用一个2的幂的大小。它不应该使用素数吗?更好的是,“素数”或“两个幂”作为哈希表大小?HashMap
使用 2 的幂可以有效地屏蔽哈希代码的顶部位。因此,在这种情况下,质量较差的哈希函数可能执行得特别差。
Java通过不信任对象的实现并对其结果应用第二级散列来缓解这种情况:HashMap
hashCode()
将补充哈希函数应用于给定的哈希代码,这可以防止质量差的哈希函数。这一点至关重要,因为 HashMap 使用两个长度的幂哈希表,否则会遇到哈希代码的冲突,而哈希代码在较低位上没有差异。
如果你有一个很好的哈希函数,或者做一些类似于什么的事情,你是否使用素数等作为表大小并不重要。HashMap
另一方面,如果哈希函数是未知的或质量差的,那么使用素数将是一个更安全的赌注。但是,这将使动态大小的表更难实现,因为突然之间,您需要能够生成质数,而不仅仅是将大小乘以常数因子。
标准的HashMap实现有一个方法,可以重新哈希对象的哈希码以避免这个陷阱。hash()
方法前面的注释如下:hash
/**
* Retrieve object hash code and applies a supplemental hash function to the
* result hash, which defends against poor quality hash functions. This is
* critical because HashMap uses power-of-two length hash tables, that
* otherwise encounter collisions for hashCodes that do not differ
* in lower bits. Note: Null keys always map to hash 0, thus index 0.
*/