Java Hashtable 如何根据 hashcode 计算元素的放置位置? [复制]

Posted

技术标签:

【中文标题】Java Hashtable 如何根据 hashcode 计算元素的放置位置? [复制]【英文标题】:How does Java Hashtable calculate where to place an element based on hashcode? [duplicate] 【发布时间】:2021-02-27 13:12:13 【问题描述】:

在 Java 中,Hashtable 具有数量等于其容量的桶。现在它如何确定必须将对象存储在特定存储桶中?我知道它使用对象的哈希码,但哈希码是一个奇怪的长字符串,哈希表对哈希码做了什么来确定入口的位置?

【问题讨论】:

but hashcode is a weird long string - 没有。 hashCode() 返回一个 int 一个散列码可以是任何东西,但在Java中散列码只是一个int 你看过HashTable的源码吗? 【参考方案1】:

我知道它使用对象的哈希码,但哈希码是一个奇怪的长字符串,哈希表对哈希码做了什么来确定入口的位置?

哈希码不是“奇怪的长字符串”。它是一个 32 位有符号整数。

(我认为您混淆了哈希码以及调用 Object::toString 时得到的内容......这是一个由哈希码和 Java 内部类型名称组成的字符串。)

那么HashMapHashTable(以及HashSetLinkedHashMap)实际上做了什么:

调用hashCode()获取32位整数, 对整数执行一些特定于实现的修改1, 通过删除符号位将错位整数转换为非负整数, 计算数组索引(对于存储桶)为value % array.length,其中array 是哈希表的当前哈希链(或树)数组。

1 - HashMap / HashTable 的一些实现执行一些简单/廉价的按位修改。目的是在hashcode值的低几位分布不均匀的情况下减少聚类。

【讨论】:

【参考方案2】:

依赖于实现(例如,如果你依赖它以这种方式工作,你的代码就会被破坏;HashMap 保证的东西在它的 javadoc 中有详细说明,而我要输入的内容都没有在那里):

哈希只是一个数字。大约在-20亿到+20亿之间。你看到的那个“长长的奇怪的字符串”只是向你展示它的一种更方便的方式。

首先,该数字的高位与低位混合(实际上,高位与低位进行异或):12340005 变成 12341239。

然后,这个数字除以当前有多少桶,但结果被扔掉了,这是我们感兴趣的余数。这个余数必须是 0 或更高,并且永远不会超过 '# of buckets there are ',所以总是准确地指向其中一个桶。

这是对象进入的桶。

如果存储桶变得太大,则调整大小。

更多信息,HashMap 和 HashSet 都是开源的 - 看看吧。

【讨论】:

Wilfred 可能不是故意的,但问题是关于HashTable 而不是HashMap。 这正是我所需要的。非常感谢,我只是想知道这一点。【参考方案3】:

关于 jdk7 的行为,请参阅:

https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/Hashtable.java#L358

int index = (hash & 0x7FFFFFFF) % tab.length;

这是哈希表的常用技术。第一位被丢弃(使值变为正)。索引是按表大小划分的remainder。

【讨论】:

以上是关于Java Hashtable 如何根据 hashcode 计算元素的放置位置? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Java中的Hashtable如何根据值获取键?

如何获得Hashtable中所有key的值和value的值

开放地址法实现HashTable

HashMap Hashtable LinkedHashMap 和TreeMap

如何对 Java Hashtable 进行排序?

Java 如何对 HashMap 或 HashTable 中的项目进行排序?