利用LinkedHashMap的accessOrder=true和重写removeEldestEntry可简洁实现线程不安全的本地LRU缓存:启用访问顺序使头结点为最久未访问项,重写removeEldestEntry在put后自动驱逐超容条目,返回size()>maxSize即可维持容量上限。

利用 LinkedHashMap 的 accessOrder = true 和重写 removeEldestEntry,可以非常简洁地实现一个线程不安全但高效、无额外依赖的本地 LRU 缓存。
启用访问顺序模式
LinkedHashMap 默认按插入顺序维护节点,但构造时传入 true 作为第三个参数,即可切换为访问顺序(access-order):每次 get 或 put 都会将对应节点移到链表尾部。这样,头结点始终是最久未被访问的条目,为 LRU 踢出提供天然顺序基础。
示例构造方式:
new LinkedHashMap<K, V>(initialCapacity, loadFactor, true)
重写 removeEldestEntry 控制容量上限
该方法在每次 put(或 putAll)后被调用,接收当前最老的节点(即链表头),返回 true 则删除它。只需在此判断 size 是否超过预设阈值:
- 返回
size() > maxSize即可自动维持最大容量 - 注意:该方法不拦截
get,所以仅靠它无法限制只读场景下的内存占用;但对典型「读多写少 + 定长缓存」已足够 - 如果需要更精细策略(如带过期时间),需额外封装,不能仅依赖此钩子
完整最小可行缓存实现
以下是一个轻量级 LRU 缓存模板(无并发控制,适合单线程或外部同步场景):
对设计或页面进行 WCAG 2.1 AA 无障碍审计。触发关键词:“audit accessibility”、 “check a11y”、 “is this accessible?” 或在审查设计时使用。
public class LRUCache<K, V> extends LinkedHashMap<K, V> {
private final int maxSize;
public LRUCache(int maxSize) {
super(16, 0.75f, true); // accessOrder = true
this.maxSize = maxSize;
}
@Override
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
return size() > maxSize;
}
}
使用时直接 new 出实例,调用 put/get 即可获得 LRU 行为,无需手动维护顺序或驱逐逻辑。
注意事项与边界情况
线程安全性:LinkedHashMap 本身非线程安全。若需多线程使用,可包装为 Collections.synchronizedMap(new LRUCache(...)),但会损失部分性能;更推荐用 ConcurrentHashMap 配合显式 LRU 管理,或选用 caffeine 等成熟库。
key 的 equals/hashCode 必须正确实现:否则 get 可能命中失败,导致误踢或重复缓存。
removeEldestEntry 不会在构造或 clear 时触发:它只响应写操作后的状态检查,因此初始化后直接 put 超量元素才会开始淘汰。

















