实现 LRU 缓存
使用 Map 实现一个 LRU(最近最少使用)缓存淘汰算法
问题
实现一个 LRU(Least Recently Used)缓存函数,当缓存达到上限时,自动删除最近最少使用的数据。
LRU 缓存常用于浏览器缓存站点信息,当内存有限时,优先删除最不常用的数据。
需求:
put(key, value)方法写入缓存,相同 key 则覆盖- 缓存达到上限时,删除最久未使用的数据
get(key)方法读取缓存,并将该数据标记为最近使用get操作时间复杂度为 O(1)
解答
数据结构选择
使用 Map 实现,因为:
- Map 的遍历顺序就是插入顺序,新数据在后,旧数据在前
- Map 的查找是 O(1) 复杂度
- 最前面的数据就是最久未使用的数据
完整实现
class LRUCache {
constructor(n) {
this.size = n; // 最大缓存数量
this.data = new Map(); // 缓存空间
}
put(domain, info) {
// 如果 key 已存在,先删除旧数据
if (this.data.has(domain)) {
this.data.delete(domain);
this.data.set(domain, info); // 重新插入到末尾
return;
}
// 如果缓存已满,删除最久未使用的数据(第一个)
if (this.data.size >= this.size) {
const firstKey = this.data.keys().next().value;
this.data.delete(firstKey);
}
this.data.set(domain, info); // 写入新数据
}
get(domain) {
// 如果数据不存在,返回 false
if (!this.data.has(domain)) {
return false;
}
// 获取数据并移动到末尾(标记为最近使用)
const info = this.data.get(domain);
this.data.delete(domain);
this.data.set(domain, info);
return info;
}
}
使用示例
const cache = new LRUCache(3);
cache.put('site1.com', 'info1');
cache.put('site2.com', 'info2');
cache.put('site3.com', 'info3');
cache.get('site1.com'); // 'info1',site1 变为最近使用
cache.put('site4.com', 'info4'); // 缓存已满,删除 site2(最久未使用)
cache.get('site2.com'); // false,已被删除
关键点
- Map 的遍历顺序即插入顺序,利用这个特性维护使用顺序
- 删除数据时从 Map 前面删除,因为最前面是最久未使用的
- 更新数据时先删除再插入,将数据移到末尾表示最近使用
Map.keys().next().value获取第一个 key,时间复杂度 O(1)- 读取数据后也要移动到末尾,保持 LRU 语义正确
目录