记录linkedHashMap

93 阅读2分钟

概述

基于哈希表和双向链表的数据结构。与普通的 HashMap 不同,LinkedHashMap 在保持键值对插入顺序的同时,还提供了按照插入顺序或访问顺序进行迭代的能力。

如何实现有序性

// LinkedHashMap 继承自 HashMap
public class LinkedHashMap<K,V> extends HashMap<K,V> {
// LinkedHashMap.Entry 表示双向链表的头结点和尾结点
transient LinkedHashMap.Entry<K,V> head, tail;

// accessOrder 为 true 表示按照访问顺序,否则按照插入顺序
final boolean accessOrder;

// ...

// 重写 put 方法,在插入元素时构建双向链表
@Override
Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
    LinkedHashMap.Entry<K,V> p =
        new LinkedHashMap.Entry<>(hash, key, value, e);
    linkNodeLast(p); // 将新节点连接到链表的尾部
    return p;
}

// ...

// 当访问一个元素时,将元素移动到链表的尾部,以实现访问顺序
@Override
void afterNodeAccess(Node<K,V> e) {
    LinkedHashMap.Entry<K,V> last;
    if (accessOrder && (last = tail) != e) {
        LinkedHashMap.Entry<K,V> p =
            (LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;
        p.after = null;
        if (b == null)
            head = a;
        else
            b.after = a;
        if (a != null)
            a.before = b;
        else
            last = b;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
        tail = p;
        ++modCount;
    }
}

// ...

}

LinkedHashMap 应用场景和使用注意点

应用场景:

  1. 保持插入顺序: 当你需要保持插入元素的顺序时,可以使用 LinkedHashMap。例如,你需要记录数据的历史操作或事件的发生顺序,这时 LinkedHashMap 可以帮助你保持这些数据的插入顺序。
  2. 访问顺序迭代: 如果你需要按照元素的访问顺序进行迭代,可以使用 LinkedHashMap。在访问顺序模式下,最近访问的元素会被移到链表的尾部,这对于实现 LRU 缓存(最近最少使用)非常有用。
  3. LRU 缓存: 由于 LinkedHashMap 可以按照访问顺序进行迭代,因此可以很容易地实现 LRU 缓存。在每次访问元素时,将元素移到链表的尾部,当缓存容量达到上限时,淘汰链表头部的元素。

使用注意点:

  1. 性能影响: 由于 LinkedHashMap 需要维护链表结构,因此在插入、删除和查找元素时可能会略微影响性能。如果性能是关键问题,需要仔细考虑是否使用 LinkedHashMap
  2. 内存消耗: 由于 LinkedHashMap 需要额外的链表结构来维护有序性,可能会占用更多的内存空间,特别是在存储大量元素时。需要根据应用场景权衡内存和有序性。
  3. 并发问题: LinkedHashMap 并没有在多线程环境下提供特定的线程安全保障,如果需要在多线程环境下使用,可以考虑使用 Collections.synchronizedMap 方法包装一层。
  4. 选择迭代模式: LinkedHashMap 提供了两种迭代模式:插入顺序和访问顺序。在构造 LinkedHashMap 时,通过设置 accessOrder 参数来选择迭代模式。需要根据具体需求选择适合的模式。
  5. 性能优化: 如果在插入元素时需要频繁地移动元素位置,可能会影响性能。在性能敏感的场景中,需要评估性能并进行必要的优化。