好的,阿杰 😄,我帮你整理一份 Java 集合框架中 LinkedHashMap 的详细解析,从概念、原理到常用方法和场景,都讲清楚。
📝 Java 集合 —— LinkedHashMap 详解
一、概念
- LinkedHashMap 是 HashMap 的子类,实现了 Map 接口
- 特点:
- 键值唯一(Key 唯一)
- 有序:保持 插入顺序(Insertion Order) 或 访问顺序(Access Order)
- 允许 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
特性 | HashMap | LinkedHashMap | TreeMap |
---|---|---|---|
有序性 | 无序 | 插入顺序/访问顺序 | 键的自然顺序或 Comparator |
线程安全 | 否 | 否 | 否 |
null 键 | 允许一个 | 允许一个 | 不允许 |
null 值 | 允许 | 允许 | 允许 |
底层实现 | 数组 + 链表 / 红黑树 | 数组 + 链表 + 双向链表 | 红黑树 |
使用场景 | 高性能查找 | 有序缓存/迭代顺序 | 按键排序 |
六、使用场景
- 保留插入顺序的 Map
- 当你希望遍历时按照元素插入顺序显示
- 实现 LRU 缓存
- 使用
accessOrder = true
+removeEldestEntry()
方法
- 使用
- 记录访问历史
- 统计最近使用的记录,做用户行为追踪等
七、小技巧
- 避免频繁扩容
int initialCapacity = (expectedSize / loadFactor) + 1;
LinkedHashMap<String, String> map = new LinkedHashMap<>(initialCapacity, 0.75f);
- 结合同步工具
Map<String, String> syncMap = Collections.synchronizedMap(new LinkedHashMap<>());
- 快速遍历 key 或 value
for(String key : map.keySet()) { ... }
for(Integer val : map.values()) { ... }
发表回复