【发布时间】:2014-01-21 14:27:00
【问题描述】:
【问题讨论】:
-
为什么不打开HashTable/HashMap的实现/源码看一下?? ..docs.oracle.com/javase/7/docs/api/java/util/Hashtable.html
【问题讨论】:
数组下标大多等价于哈希值(嗯,哈希值修改了数组的大小),所以根本不需要将它存储在数组中。
至于实际数组包含什么,有几个选项:
如果我们使用separate chaining:
对具有该哈希值的所有元素的链表的引用。所以:
LinkedList<E>[]
链表节点(即链表的头部) - 类似于第一个选项,但我们只是直接从链表开始,而不通过单独引用它来浪费空间。所以:
LinkedListNode<E>[]
如果我们使用open addressing,我们只是存储实际元素。如果有另一个元素具有相同的哈希值,我们使用一些可重现的技术来找到它的位置(例如,我们只是尝试下一个位置)。所以:
E[]
可能还有其他一些选项,但以上是最著名的,分离链是最受欢迎的(据我所知)
* 我假设对泛型和 Java/C#/C++ 语法有些熟悉 - E 这里只是我们要存储的元素的类型,LinkedList<E> 表示 LinkedList 存储类型为 @987654329 的元素@。 X[] 是一个包含 X 类型元素的数组。
【讨论】:
hashCode % buckets.Length找索引。
桶数组中的内容很大程度上取决于哈希表中存储的内容,以及冲突解决策略。
当您使用linear probing 或另一个open addressing technique 时,您的存储桶表存储键或键值对,具体取决于您的哈希表的使用情况 *。
当您使用 separate chaining technique 时,您的存储桶数组会存储成对的键和链接结构的标头(例如链表)。
关于桶数组要记住的重要一点是,它在哈希码和一组零个或多个键之间建立了映射。换句话说,给定一个哈希码和一个桶数组,你可以在恒定时间内找出与这个哈希码相关的可能键是什么(枚举候选键可能是线性的,但找到第一个需要是常数时间,以满足哈希表对平均分摊常数时间插入和常数时间搜索的性能保证。
* 如果您的哈希表用于检查成员资格(即它表示一组键),则桶数组存储键;否则,它存储键值对。
【讨论】:
实际上,已计算(通过散列键)进入该存储桶的条目的链接列表。
【讨论】:
在 HashTable 中,大多数时候都会发生冲突。那是当不同的元素具有相同的哈希值时。具有相同 Hash 值的元素存储在一个桶中。因此,对于每个哈希值,您都有一个存储桶,其中包含具有该哈希值的所有元素。
【讨论】:
桶是键值对的链表。哈希索引是一个 告诉“哪个桶”,而键值对中的“键”就是告诉“那个桶中的哪个条目”的那个。 也签出 hashing in Java -- structure & access time,我已经在那里告诉了更多细节。
【讨论】: