我正在寻找对两个不同但相关的论点的验证——那些高于(A)和低于(B)的第一行行注释。
(A) HashMap的结构方式是:
HashMap是一个普通的表。那就是直接内存访问(DMA)。
HashMap (或一般的散列)背后的整个想法首先是将这种恒定时间的内存访问用于
a.) 通过它们自己的数据内容(<K,V>)访问记录,而不是通过它们在 DMA 中的位置(表索引)
b.) 管理可变数量的记录——一些不具有给定大小的记录,并且在整个使用该结构的过程中可能/不保持大小不变。
因此,Java Hash 中的整体结构是:
a table: table // 我正在使用HashMap中使用的标识符
该表的每个单元格都是一个桶。
每个桶是一个Entry类型的链表——即这个链表的每个节点(不是Java/API 的链表,而是数据结构)都是Entry 类型,而Entry又是一个<K,V> 对。
当有一个新的对被添加到哈希中时,会为这个 <K,V> 对计算一个唯一的hashCode 。这个hashCode是这个<K,V>在表中的索引键——它告诉这个<K,V>将进入哪个桶。注意:hashCode通过函数hash()(在HashMap中为一个)“规范化”,以更好地适应table的当前长度。indexFor()也用于确定 < K,V > 将进入哪个桶,即表的单元格。
当bucket确定后,<K,V>被添加到这个bucket中链表的开头——结果,它是这个bucket中的第一个<K,V>条目,并且是链表的第一个条目-list-that-already-existed 现在是这个新添加的条目指向的“下一个”条目。
//================================================= ================
(B) 根据我在HashMap中看到的,表的大小调整——哈希仅在基于哈希大小和容量(即当前和最大值)的决定时完成。# 整个哈希中的条目。
没有对单个存储桶大小进行重组或调整大小 - 例如“当存储桶中的 max.#entries 超过此类时的“resize()”。
这是不可能的,但是有可能大量的条目可能会堆积在一个桶中,而其余的散列几乎是空的。
如果是这种情况,即每个桶的大小没有上限,则哈希不是恒定的而是线性访问——理论上是为了一件事。获取哈希中的条目需要 $O(n)$ 时间,其中 $n$ 是条目的总数。但那不应该。
//================================================= ================
我认为我没有遗漏上述(A)部分中的任何内容。
我不完全确定(B)部分。这是一个重要的问题,我正在寻找这个论点的准确性。
我正在寻找这两个部分的验证。
提前致谢。
//================================================= ================
编辑:
最大存储桶大小是固定的,即,只要存储桶中的#entries 达到最大值,就会重新构建散列 - 访问时间在理论上和使用中都是恒定的。
这不是一个结构良好但快速的解决方案,并且为了持续访问而工作得很好。
hashCodes 很可能均匀地分布在整个存储桶中,并且在达到哈希整体大小的阈值之前,任何存储桶都不太可能达到 bucket-max。这也是当前 HashMap 设置使用的假设。
也基于下面彼得劳里的讨论。