javascript 的 map 天然支持插入顺序遍历,适合作为 lru 缓存底层结构;每次 get/set 通过 delete + set 将键值对移至末尾,淘汰时删除第一个键,时间复杂度均为 o(1)。

JavaScript 中的 Map 天然支持插入顺序遍历,且 keys()、values()、entries() 返回的迭代器按插入顺序产出,这使得它非常适合作为 LRU(Least Recently Used)缓存的底层数据结构——无需额外维护链表或时间戳,只需在每次 get 或 set 时把对应项移到末尾即可。
核心思路:利用 Map 的插入顺序特性
Map 的键值对是按插入顺序保存的,最早插入的在最前面,最新插入/访问的在最后面。LRU 要求“最近最少使用”的项被优先淘汰,也就是淘汰 Map 中第一个键(Map.keys().next().value)。每次 get 访问后,把该 key 对应的项删掉再重新 set 一遍,就自然挪到了末尾;set 时若容量超限,直接删除第一个 entry。
实现一个基础 LRU 缓存类
以下是一个简洁、可运行的 LRU Cache 实现:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
class LRUCache {
constructor(capacity) {
this.capacity = capacity;
this.cache = new Map();
}
get(key) {
if (!this.cache.has(key)) return -1;
const val = this.cache.get(key);
this.cache.delete(key);
this.cache.set(key, val); // 重设 → 移至末尾
return val;
}
set(key, value) {
if (this.cache.has(key)) {
this.cache.delete(key);
} else if (this.cache.size >= this.capacity) {
// 淘汰最久未使用的(即第一个)
this.cache.delete(this.cache.keys().next().value);
}
this.cache.set(key, value);
}
}
关键细节与注意事项
-
delete + set 是必须的:不能只调用
get,因为 Map 不会自动更新访问顺序;必须显式删除再插入,才能保证顺序刷新。 -
keys().next().value 安全可用:当
Map非空时,this.cache.keys().next().value总能取到第一个键;配合size >= capacity判断,可避免空删。 -
时间复杂度:
get和set均为 O(1) 平均时间(Map 的哈希操作),不依赖遍历,比手写双向链表+哈希更简洁且性能足够好。 - 不支持弱引用或过期策略:这是一个纯 LRU 实现;如需 TTL(time-to-live),需额外记录时间戳并配合定时清理或惰性检查。
简单测试示例
const cache = new LRUCache(2);
cache.set(1, 1);
cache.set(2, 2);
console.log(cache.get(1)); // 1 → 访问后 1 移至末尾
cache.set(3, 3); // 淘汰 key=2(此时 Map 顺序为 [1,3])
console.log(cache.get(2)); // -1
console.log(cache.get(3)); // 3
cache.set(4, 4); // 淘汰 key=1
console.log(cache.get(1)); // -1
console.log(cache.get(3)); // 3
console.log(cache.get(4)); // 4
不复杂但容易忽略:Map 的顺序行为是规范保障的,不是偶然,放心用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










