--- title: "03-LinkedHashMap" created: 2025-12-02 tags: - Java --- # LinkedHashMap > [!note] 定位说明 > Map 系列第 3 篇。HashMap + 双向链表:**accessOrder=true 就是 LRU 缓存的现成地基**(配 removeEldestEntry),本篇含完整 LRU 实现示例。 ## LinkedHashMap 是什么? `LinkedHashMap` 是 Java 集合框架中 `HashMap` 的一个子类,**底层基于哈希表 + 双向链表**,它不仅具备 `HashMap` 的快速查找特性(平均 O(1)),还可以**保持元素的插入顺序或访问顺序**。 > 它继承了 `HashMap` 的所有 API,但对**遍历顺序**进行了增强。 ## 核心特性(区别于 HashMap) | 特性 | LinkedHashMap 说明 | | --- | --- | | 顺序可控 | 可以按 **插入顺序** 或 **访问顺序** 进行遍历 | | 基于双向链表 | 在每个节点中维护 `before` 和 `after` 指针,维护元素顺序 | | 查询效率 | 和 `HashMap` 一样,查找时间复杂度为 O(1) | | 插入/删除效率 | 略低于 `HashMap`,维护顺序结构需额外指针操作 | | 线程安全 | 非线程安全,需要手动加锁或使用 `Collections.synchronizedMap()` 包装 | | null 支持 | 支持一个 null 键和多个 null 值 | ## 常用构造函数 ```java // 默认按插入顺序排序 LinkedHashMap map = new LinkedHashMap<>(); // 指定初始容量、负载因子 LinkedHashMap map = new LinkedHashMap<>(16, 0.75f); // accessOrder = true 表示按访问顺序排序(用于 LRU 缓存) LinkedHashMap map = new LinkedHashMap<>(16, 0.75f, true); ``` ## 使用示例 ### 插入顺序遍历(默认) ```java Map map = new LinkedHashMap<>(); map.put("A", 1); map.put("C", 3); map.put("B", 2); for (String key : map.keySet()) { System.out.print(key + " "); // 输出顺序:A C B } ``` ### 访问顺序遍历(accessOrder = true) ```java Map map = new LinkedHashMap<>(16, 0.75f, true); map.put("A", 1); map.put("B", 2); map.put("C", 3); map.get("A"); map.get("C"); for (String key : map.keySet()) { System.out.print(key + " "); // 输出顺序:B A C(按访问顺序) } ``` ## 实际应用场景 ### 保留插入顺序(日志记录、数据导出) 使用 `LinkedHashMap` 可以按用户插入的顺序输出数据,常用于: - 构建 JSON 时保持字段顺序 - 数据库同步、配置加载按原顺序处理 ### 实现 LRU 缓存(最近最少使用) 利用 `accessOrder = true` + 重写 `removeEldestEntry()`: ```java class LRUCache extends LinkedHashMap { private final int capacity; public LRUCache(int capacity) { super(capacity, 0.75f, true); // accessOrder = true this.capacity = capacity; } @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > capacity; // 超出容量自动移除最旧访问的 } } ``` 使用示例: ```java LRUCache cache = new LRUCache<>(3); cache.put(1, "A"); cache.put(2, "B"); cache.put(3, "C"); cache.get(1); cache.put(4, "D"); System.out.println(cache.keySet()); // 输出 [3, 1, 4] ``` ## 使用注意事项 | 注意点 | 说明 | | --- | --- | | 不是线程安全 | 多线程场景使用 `Collections.synchronizedMap()` 或 `ConcurrentHashMap` | | null 键值 | 和 `HashMap` 一样,允许一个 null 键,多个 null 值 | | 不保证绝对有序性 | 只有 `accessOrder=false` 时才完全按插入顺序;设置为 true 后顺序会因访问而变化 | | 删除最旧元素需重写 removeEldestEntry() | 用于实现缓存淘汰策略 | ## 总结一句话 > `LinkedHashMap` 是结合了 `HashMap` 快速查找 和 `双向链表` 顺序控制能力的集合类,适用于需要有序遍历或实现 > LRU 缓存等高级需求的场景。 [[04-LinkedHashMap源码剖析|LinkedHashMap源码剖析]] --- ⬅️ [[02-HashMap源码解析|HashMap源码解析]] 🏠 [[00-Java|00-Java]] ➡️ [[04-LinkedHashMap源码剖析|LinkedHashMap源码剖析]]