java 为什么linkedhashmap维护双向链表进行迭代

sdnqo3pr  于 2023-06-20  发布在  Java
关注(0)|答案(6)|浏览(157)

因为任何线程都没有内部合理的解释。请给予我确切的理由。
1.对于插入顺序,使用单链表就足够了,但为什么不呢?
1.在这种情况下,双向链表如何提高性能?
1.所有的方法都是从hashmap xpt 4方法继承的,那么hashmap的迭代器不维护顺序,而linkedhashmap维护顺序?

ohfgkhjo

ohfgkhjo1#

你是对的,你只需要维护一个单链表来跟踪插入顺序。但是为了有效地维护一个单链表,你实际上需要一个双向链表。
按顺序考虑三个条目

A ---> B ---> C

假设你删除了B。显然,A现在应该指向C。但是,除非您知道B之前的条目,否则您无法有效地说出哪个条目现在应该指向C。要解决这个问题,需要条目指向两个方向。

--->   ---> 
A      B      C
  <---   <---

这样,当您删除B时,您可以查看B之前和之后的条目(AC)并更新,以便AC相互指向。
LinkedHashMap保持插入顺序,而HashMap没有,尽管事实上除了4个方法外,所有方法都是继承的,这是因为它写得非常巧妙。大多数特定于实现的操作都是HashMap.Entry的成员,而不是HashMapLinkedHashMap具有private staticLinkedHashMap.Entry,它扩展了HashMapstaticHashMap.Entry。例如,当您调用putremove时,LinkedHashMap的代码可以与HashMap的代码相同,因为是 * 条目本身 * 跟踪之前和之后的信息。例如,下面是我在上面解释的LinkedHashMap.Entry.remove()的完整代码

private void remove() {
    before.after = after;
    after.before = before;
}
fjnneemd

fjnneemd2#

LinkedHashMap基本上为每个条目维护两个指针,即-:之前,之后
正如名称所暗示的,指针都用于排序目的,并且用于在插入或删除的情况下调整指针。

t98cgbkg

t98cgbkg3#

为了维护插入顺序,有双重LinkedList。在任何时间点,您都可以向前移动节点或向后移动节点。但是,如果你有一个LinkedList,如果你的指针移动到最后一个元素,你又需要从初始点开始,你不能移动到前一个节点。

kiayqfof

kiayqfof4#

我还想补充的一点是,LinkedHashMap也可以用作LRU缓存,方法是通过其构造函数将其accessOrder布尔值设置为true。
现在LinkedHashMap维护两个指针head(LinkedHashMap中最年长的)和tails(LinkedHashMap中最年轻的)。因此请记住,当您将accessOrder设置为true时,它将停止维护插入顺序,并开始表现得像一个适当的LRU缓存。
现在,当LRU缓存超过其限制并且我们想要删除最老的条目时,因为它在内部维护DoublyLinkedList,所以删除最老的条目相对较快,因为它维护两个指针(头部和尾部),可以在两个方向上移动,或者我们可以说如果它是用于删除最老条目的Singly LinkedList,则我们需要遍历所有节点,然后删除它。由于有了headtails指针,它可以很容易地完成,只需删除最后一个节点(最老的一个),通过tails指针的帮助到达那里,并采取最后一个节点的前一个指针,使LinkedHashMap中DoublyLinkedList的倒数第二个节点tail

yqkkidmi

yqkkidmi5#

其他答案涵盖了为什么目前需要双向链表。Java 21增加了一个额外的原因:一个reversed方法被添加到LinkedHashMap中,它提供了一个反向的Map视图。需要向后链接来有效地向后遍历列表以提供该视图。

ybzsozfc

ybzsozfc6#

LinkedHashMap可用于维护插入顺序和访问顺序。LinkedHashMap继承了hashmap在bucket中维护列表的相同功能,所以使用了next引用。
为了保持插入顺序,他们使用了双向链表(在引用之前使用**,在引用之后使用**),但这可以通过使用单向链表来完成。同时,它们必须实现访问顺序功能,并且需要频繁地将元素移动到末尾,并且需要频繁删除频繁删除,因此它们使用了双向链表。

相关问题