import { DoublyLinkedList, DoublyLinkedListNode } from './doublyLinkedList'; /** * LRU缓存项 * * @template K 键的类型 * @template V 值的类型 */ interface LruCacheItem { key: K; value: V; } /** * LRU (Least Recently Used) 缓存实现 * 使用双向链表 + Map 实现 O(1) 时间复杂度的所有操作 * * @template K 键的类型 * @template V 值的类型 */ export class LruCache { private readonly maxSize: number; private readonly cache = new Map>>(); private readonly lru = new DoublyLinkedList>(); /** * 创建LRU缓存实例 * * @param maxSize 最大缓存大小 */ constructor(maxSize: number) { if (maxSize <= 0) { throw new Error('Max size must be greater than 0'); } this.maxSize = maxSize; } /** * 获取缓存值 * * @param key 键 * @returns 缓存的值,如果不存在则返回undefined */ get(key: K): V | undefined { const node = this.cache.get(key); if (node) { // 将访问的节点移动到链表尾部(最近使用) this.lru.moveToLast(node); return node.data.value; } return undefined; } /** * 设置缓存值 * * @param key 键 * @param value 值 * @param onEvict 当有项目被驱逐时的回调函数 */ set(key: K, value: V, onEvict?: (evictedKey: K, evictedValue: V) => void): void { const existingNode = this.cache.get(key); // 如果键已存在,更新值并移动到最近使用 if (existingNode) { existingNode.data.value = value; this.lru.moveToLast(existingNode); return; } // 如果缓存已满,移除最少使用的项 if (this.cache.size >= this.maxSize) { const oldestNode = this.lru.first; if (oldestNode) { const { key: evictedKey, value: evictedValue } = oldestNode.data; this.cache.delete(evictedKey); this.lru.removeFirst(); if (onEvict) { onEvict(evictedKey, evictedValue); } } } // 添加新项到链表尾部(最近使用) const newNode = this.lru.addLast({ key, value }); this.cache.set(key, newNode); } /** * 检查键是否存在 * * @param key 键 * @returns 是否存在 */ has(key: K): boolean { return this.cache.has(key); } /** * 删除指定键的缓存 * * @param key 键 * @returns 是否成功删除 */ delete(key: K): boolean { const node = this.cache.get(key); if (node) { this.cache.delete(key); this.lru.remove(node); return true; } return false; } /** * 清空缓存 * * @param onEvict 清空时对每个项目的回调函数 */ clear(onEvict?: (key: K, value: V) => void): void { if (onEvict) { this.lru.forEach(item => { onEvict(item.key, item.value); }); } this.cache.clear(); this.lru.clear(); } /** * 获取缓存大小 * * @returns 当前缓存项数量 */ get size(): number { return this.cache.size; } /** * 获取所有键 * * @returns 所有键的数组,按最近使用顺序排列(从最少使用到最近使用) */ keys(): K[] { return this.lru.toArray().map(item => item.key); } /** * 获取所有值 * * @returns 所有值的数组,按最近使用顺序排列(从最少使用到最近使用) */ values(): V[] { return this.lru.toArray().map(item => item.value); } }