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










