为什么linkedhashmap维护迭代的双向链表

时间:2015-01-13 06:19:44

标签: java performance

由于在任何线程中都没有内部和合理的解释。 请给我确切的理由。

  1. 对于插入顺序,它足以维持单链表,但为什么不呢?

  2. 在这种情况下,双向链表如何提高性能?

  3. 所有方法都继承自hashmap xpt 4方法,然后hashmap的迭代器不维护顺序,而linkedhashmap维护顺序?

5 个答案:

答案 0 :(得分:10)

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

按顺序考虑三个条目

A ---> B ---> C

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

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

这样,当您移除B时,您只需查看BAC之前和之后的条目,然后更新{{1} }和A指向对方。

C保持广告订单的原因LinkedHashMap没有,尽管除了4种方法之外的所有方法都是继承的,但是它写得非常巧妙。大多数特定于实现的操作都是HashMap的成员,而不是HashMap.EntryHashMap有一个LinkedHashMapprivate static,其扩展了LinkedHashMap.Entry static HashMap.Entry个班级HashMap。例如,当您致电putremove时,LinkedHashMap的代码可能与HashMap的代码相同,因为它本身就是条目跟踪信息之前和之后的信息。例如,以下是我在上面解释的LinkedHashMap.Entry.remove()的完整代码

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

答案 1 :(得分:3)

LinkedHashMap基本上为每个条目维护两个指针 - : 之前,之后

如名称所示,这两个指针都用于排序目的,用于在插入或删除时调整指针。

答案 2 :(得分:1)

要维护广告订单,会有双重的LinkedList。在任何时候你都可以向前移动节点或向后节点。但是如果你的指针移动到最后一个元素,你有单个LinkedList,你再次需要从初始点开始,你不能移动到前一个节点。

答案 3 :(得分:0)

我还要补充的一点是LinkedHashMap也可以通过其构造函数将accessOrder boolean设置为true来用作LRU Cache。

现在,LinkedHashMap维护了两个指针head(LinkedHashMap中最年长的)和tails(最年轻的LinkedHashMap)。因此,请记住,当您将accessOrder设置为true时,它会停止维护插入顺序并开始表现得像正确的LRU缓存。

现在当LRU缓存超过其限制并且我们想要删除最老的条目时,因为它在内部维护DoublyLinkedList,删除最旧的条目相对较快,因为它保持两个指针(头部和尾部)可以在两个方向上移动或我们可以说,如果它是一个单一链接列表,用于删除最老的条目,我们需要遍历所有节点,然后删除它。感谢指针headtails,可以通过在tails指针的帮助下到达最后一个节点(最远的一个节点)并将最后一个节点的前一个指针移到那里来轻松完成LinkedHashMap中DoublyLinkedList的第二个节点tail

答案 4 :(得分:-1)

LinkedHashMap可用于维护广告订单和维护访问顺序。 LinkedHashMap继承了bucket中维护列表的hashmap的相同功能,因此使用 next 引用。

为了维护插入顺序,他们使用了双向链表(在之前使用,在之后使用),但这可以通过使用单链表来完成。同时,他们必须实现访问顺序功能,并且需要频繁移动元素到最后,并且需要频繁删除频繁删除,他们使用双向链表。