我试图理解这些数据结构实际上是如何可视化的。据说TreeMap
将条目放在自然顺序 [密钥]中,LinkedHashMap
将条目放入插入它们的顺序中。
我的问题是,对每个数据结构的迭代是否意味着遍历所有遍布所有桶(或内部数组)的元素?
我的理解是,例如,在TreeMap
的情况下,具有相同哈希码的元素被放置在 Tree 结构中[某种] 。因此,如果TreeMap
在16个索引[在其数据库数组]中的 6 中包含元素,则它将包含 6 Tree
- - 每人一个。
同样,在LinkedHashMap
(实际上应该被称为 DoublyLinkedHashMap )的情况下,每个存储桶都会有一个双重链接列表。
那么,迭代实际上是如何发生的?是否会在所有存储桶中的所有元素上发生,还是仅在单个存储桶的元素上发生?我的假设错了吗?
P.S。似乎在 Java 8 中,HashMap
实现使用Tree
或LinkedList
,具体取决于每个包含8个或更少的桶的元素数量分别为6个元素!
答案 0 :(得分:1)
正常实现的源代码位于Oracle JDK安装附带的src.zip文件中。
TreeMap
:如文档中所示,它是一棵红黑树。对密钥进行简单转发迭代的关键代码是方法static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t)
。它以左父 - 右的顺序递归扫描树。它取决于根据键的顺序插入树中的节点的排序。
LinkedHashMap
:它在到达顺序上有一个双向链表,强加在带有桶的哈希结构之上。嵌套类Entry
扩展HashMap.Node
以添加before
和after
引用。正常转发迭代遵循after
链。
答案 1 :(得分:0)
补充@patricia-shanahan的回答:
要将可视化添加到LinkedHashMap
(这是针对 Java 7 ,旧版本为 Java 8 不同),假设元素按顺序添加A
,B
,...,E
(并假设A
有一个哈希码,使其落入存储桶0或D
的哈希码放置在存储桶3)中,具有4个容器的HashMap
将具有以下布局(“ | ”表示存储桶链接列表中HashMap.Entry<K, V>
中的下一个属性变量):
║ 0 ║ 1 ║ 2 ║ 3 ║
╠═══╬═══╬═══╬═══╬
║ A ║ ║ B ║ D ║
╠═|═╬═══╬═|═╬═|═╬
║ E ║ ║ C ║nul║
╠═|═╬═══╬═|═╬═══╬
║nul║ ║nul║ ║
╠═══╬═══╬═══╬═══╬
此外,每个元素A
... E
都会有两个额外的引用(LinkedHashMap.Entry<K, V>
之前和之后):
A---->B---->C---->D---->E
^____|^____|^____|^____|
总的来说,每个LinkedHashMap.Entry<K, V>
都有3个引用:next
,after
和before
。因此,存在单个元素,即A
(类型为LinkedHashMap.Entry<K, V>
),具有三个引用。 TreeMap
还有三个引用,但它们针对不同目的引用了其他TreeMap.Entry<K, V>
:parent
,left
和right
。