【问题标题】:why linkedhashmap maintains doubly linked list for iteration为什么linkedhashmap维护双向链表进行迭代
【发布时间】:2015-01-13 06:19:43
【问题描述】:

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

  1. 对于插入顺序来说,用单链表维护就足够了,但为什么不呢?

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

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

【问题讨论】:

  • 我不认为双向链表有助于排序,它只是让遍历列表更容易
  • 它不会让遍历变得更容易。它只是使删除地图条目更有效。
  • 这样你就可以倒退了。

标签: java performance


【解决方案1】:

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

依次考虑三个条目

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;
}

【讨论】:

  • 很好,简单地说。
  • 非常感谢!!现在我明白了为什么单链表还不够。
【解决方案2】:

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

顾名思义,这两个指针都用于排序目的,并用于在插入或删除时调整指针。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 我不认为双向链表有助于排序,它只是让遍历列表更容易
    • 如果你看到内部HashMap是基于linkedList的。因此,如果您有诸如之前或之后插入了哪个节点之类的信息,那么这只是一个排序。
    • 一个单链表足以维持一个顺序。这不是他们为什么在这种情况下使用双向链表的正确解释。
    • 并且应该注意LinkedHashMap.keySet().iterator()返回一个普通的Iterator而不是ListIterator。您不能以反向插入顺序迭代键......无论使用双向链表的事实如何。 API 不允许这样做。
    【解决方案4】:

    我还想补充一点,LinkedHashMap 也可以用作 LRU 缓存,方法是通过其构造函数将其 accessOrder 布尔值设置为 true。

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

    现在,当 LRU 缓存超出其限制并且我们想要删除最旧的条目时,因为它在内部维护了 DoublyLinkedList,所以删除最旧的条目相对较快,因为它维护了两个可以双向移动的指针(头和尾)或我们可以说如果它是用于删除最旧条目的单链表,我们需要遍历所有节点然后将其删除。多亏了指针headtails,它可以很容易地通过在tails 指针的帮助下到达那里删除最后一个节点(最老的一个)并取最后一个节点的前一个指针来制作倒数第二个节点tail LinkedHashMap中的DoublyLinkedList。

    【讨论】:

      【解决方案5】:

      LinkedHashMap 可用于维护插入顺序和访问顺序。 LinkedHashMap 继承了 hashmap 的相同功能,用于在桶中维护列表,所以使用 next 参考。

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

      【讨论】:

        猜你喜欢
        • 2013-10-10
        • 2016-01-22
        • 2015-07-14
        • 1970-01-01
        • 2019-07-03
        • 2015-07-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多