如果 Hashtables 使用单独的链接,为什么重复键是不可能的?

问题描述

所以我对这个有点困惑。 如果 Hashtables 使用单独的链接(或线性探测),为什么以下不会打印出两个值?

         Hashtable<Character,Integer> map = new Hashtable<>();
         map.put('h',0);
         map.put('h',1);
         System.out.println(map.remove('h')); // outputs 1
         System.out.println(map.get('h')); // outputs null

我试图理解为什么在给定 2 个相同的键的情况下,哈希表不会使用单独的链接来存储两个值。是我理解的有点不正确,还是 Java 没有在它们的哈希表类中实现冲突处理?

一个可能联系在一起的问题是,给定一个键,使用线性探测的哈希表如何知道我们正在寻找哪个值?

提前致谢!

解决方法

我认为您误解了哈希表的工作原理。想象一下,我正在寻找一个 ID 为 227828 的人。假设我有 1000 个这样的人。我可以搜索所有 1000 个并最终找到该 ID 及其所属的人。

但是如果他们的 id 被用作哈希表中的键,那就更容易了。使用 id 作为键,假设哈希函数为偶数 id 返回 0,为奇数 id 返回 1。然后我所要做的就是找到包含偶数 id 的框。理想情况下,我只需要搜索 500 个条目即可找到键 - 即 id,并返回与其关联的值。

但是哈希函数更复杂,并且有很多这样的盒子或桶。并且可以识别适当的盒子或桶,然后搜索适当的密钥。然后返回其关联值。

,

我试图理解为什么在给定 2 个相同的键的情况下,哈希表不会使用单独的链接来存储两个值。

Map 的规范(即 javadoc)规定每个键只存储一个值。这就是 HashTableHashMap 实现的作用。

当然,单独的链接不会阻止某人实现具有该属性的哈希表。具有单独链接的哈希表上 put(key,value) 的伪代码大致如下:

  1. 计算密钥的哈希值。
  2. 根据哈希值计算哈希链数组中的索引。 (计算是 index = hash % array.length 或类似的东西。)
  3. 在计算出的索引处搜索哈希链,以查找与键匹配的条目。
  4. 如果您在链上找到了密钥的条目,请更新条目中的值。
  5. 如果您没有找到该条目,请创建一个条目并将其添加到链中。

如果对相同的键重复该操作,您将计算相同的哈希值,搜索相同的链,并找到相同的条目。然后您更新它,但仍然只有该密钥的一个条目......正如规范所要求的那样。

简而言之,上述算法满足 Map.put API 要求没有问题。