好的,阿杰 😄,我帮你整理一份 Java 集合框架中 LinkedHashMap 的详细解析,从概念、原理到常用方法和场景,都讲清楚。


📝 Java 集合 —— LinkedHashMap 详解

一、概念

  • LinkedHashMap 是 HashMap 的子类,实现了 Map 接口
  • 特点:
    1. 键值唯一(Key 唯一)
    2. 有序:保持 插入顺序(Insertion Order) 或 访问顺序(Access Order)
    3. 允许 null 键和 null 值(key 允许一个 null,value 可多个 null)

二、底层原理

1. 数据结构

  • 继承自 HashMap,底层使用 哈希表 + 双向链表
  • 每个节点(Entry)包含:
    • key
    • value
    • hash
    • next(Hash 冲突链表)
    • before / after(双向链表指针,用于维护顺序)

2. 顺序类型

  • 插入顺序(默认)
    • 元素按插入顺序迭代
  • 访问顺序(accessOrder = true)
    • 元素按访问顺序迭代(get 或 put 都算访问)
    • 用于实现 LRU 缓存(Least Recently Used)

三、构造方法

构造方法说明
LinkedHashMap()默认容量 16,加载因子 0.75,插入顺序
LinkedHashMap(int initialCapacity)指定初始容量,插入顺序
LinkedHashMap(int initialCapacity, float loadFactor)指定容量和加载因子
LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)指定顺序类型,accessOrder = true 表示访问顺序

四、常用方法

1. 基本操作

LinkedHashMap<String, Integer> map = new LinkedHashMap<>();

// 添加元素
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);

// 获取元素
map.get("B"); // 2

// 删除元素
map.remove("A");

// 判断
map.containsKey("C"); // true
map.containsValue(2); // true

// 大小
map.size();

// 遍历
for(Map.Entry<String, Integer> entry : map.entrySet()){
    System.out.println(entry.getKey() + " -> " + entry.getValue());
}

2. LRU 缓存实现

LinkedHashMap<Integer, String> lruCache = new LinkedHashMap<>(16, 0.75f, true) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<Integer, String> eldest) {
        return this.size() > 3; // 超过容量,删除最老访问的元素
    }
};

lruCache.put(1, "A");
lruCache.put(2, "B");
lruCache.put(3, "C");
lruCache.get(1); // 访问 1
lruCache.put(4, "D"); // 超过容量,删除 2

System.out.println(lruCache);

输出:

{3=C, 1=A, 4=D}

最近访问顺序更新,实现 LRU 缓存


五、LinkedHashMap vs HashMap vs TreeMap

特性HashMapLinkedHashMapTreeMap
有序性无序插入顺序/访问顺序键的自然顺序或 Comparator
线程安全
null 键允许一个允许一个不允许
null 值允许允许允许
底层实现数组 + 链表 / 红黑树数组 + 链表 + 双向链表红黑树
使用场景高性能查找有序缓存/迭代顺序按键排序

六、使用场景

  1. 保留插入顺序的 Map
    • 当你希望遍历时按照元素插入顺序显示
  2. 实现 LRU 缓存
    • 使用 accessOrder = true + removeEldestEntry() 方法
  3. 记录访问历史
    • 统计最近使用的记录,做用户行为追踪等

七、小技巧

  1. 避免频繁扩容
int initialCapacity = (expectedSize / loadFactor) + 1;
LinkedHashMap<String, String> map = new LinkedHashMap<>(initialCapacity, 0.75f);
  1. 结合同步工具
Map<String, String> syncMap = Collections.synchronizedMap(new LinkedHashMap<>());
  1. 快速遍历 key 或 value
for(String key : map.keySet()) { ... }
for(Integer val : map.values()) { ... }