removeEldestEntry() 是 LinkedHashMap 实现缓存淘汰的核心钩子方法,每次 put/putAll 后调用,返回 true 时自动删除头节点;默认按插入顺序淘汰最老项,启用 accessOrder=true 可实现 LRU;适用于固定容量 FIFO 或结合时间/频次的自定义策略,但不主动轮询、非线程安全。
linkedhashmap 的
方法是实现自定义缓存淘汰策略的核心机制,它在每次插入新元素后被调用,返回
时会自动删除最老(即最先插入)的条目。关键在于重写该方法,结合业务需求判断是否触发淘汰。
理解 removeEldestEntry() 的触发时机和作用
该方法不是在插入前检查,而是在
或
完成后、返回前被调用,参数是当前即将成为“最老”的那个 Entry(即链表头节点)。它不负责删除动作本身,只决定“要不要删”——返回
才会由 LinkedHashMap 自动移除头节点。
注意:只有在构造 LinkedHashMap 时启用访问顺序(
)才会按访问时间排序;若保持插入顺序(默认),则淘汰的是最早插入的项。
实现固定容量的 FIFO 缓存
这是最常见用法:限制缓存最大条目数,超出即淘汰最老项。
创建 LinkedHashMap 时传入初始容量、加载因子,并设
(默认)
重写
,判断
示例代码:
基于时间或使用频率的进阶策略
单纯靠 size 不够灵活,可扩展 Entry 类型或借助外部结构记录元数据:
LRU(最近最少使用)
:启用
,配合 size 限制即可,无需额外时间戳
带过期时间的缓存
:不能仅靠
实现定时过期(它不主动轮询),但可在该方法中检查 eldest 的插入/访问时间戳,如:
按访问频次淘汰
:需自行维护计数器(如用
包装 value),在
中更新,在
中比较频次阈值
注意事项与避坑点
该机制是被动触发,依赖写操作驱动,不适合强时效性场景(比如必须精确到秒过期);也不支持并发安全,默认非线程安全,高并发下需包装为
或改用
配合显式淘汰逻辑。
另外,重写时避免在方法内修改 map 状态(如调用
),可能引发
或死循环。
removeeldestentry()trueput()putAll()trueaccessOrder = trueaccessOrder = falseremoveEldestEntry()size() > maxSizeint maxSize = 100;
Map cache = new LinkedHashMap<>(16, 0.75f, false) {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > maxSize;
}
}; accessOrder = trueremoveEldestEntry()return System.currentTimeMillis() - eldest.timestamp > 60_000;AtomicIntegerget()removeEldestEntry()Collections.synchronizedMap()ConcurrentHashMapremove()ConcurrentModificationException