LRU缓存不依赖访问频次,而是按最近使用时间淘汰;若需频次计数,实为LFU策略,可用keys[]、values[]、counts[]三个平行数组实现,查找、更新、淘汰均为O(N)时间复杂度。
在 java 中,用数组实现 lru 缓存的“访问频率计数器”并不符合标准 lru 的定义——lru(least recently used)关注的是**最近使用时间顺序**,而非访问频次。但如果你实际想做的是:在数组结构基础上,**记录每个缓存项被访问的次数,并基于频次淘汰最少访问的项(即 lfu 策略)**,那可以用数组配合简单计数逻辑来实现;若坚持叫“lru 中的频率计数器”,需注意这是概念混淆,真正 lru 不依赖频次。
明确目标:用数组模拟 LFU 计数器(更贴合需求)
假设你有一个固定大小的缓存(如容量为 N),用两个平行数组维护:
- keys[]:存储键(如 String 或 Integer)
- values[]:存储对应值
- counts[]:同下标处记录该键被访问的次数(即频率计数器)
每次 get(key) 时,找到 key 对应下标,counts[i]++;每次 put(key, value) 时,若 key 已存在则更新 value 和 counts;若不存在且缓存满,则找出 counts[] 中最小值的下标(若有多个,可选最老或最前一个),替换之。
关键操作:查找、更新与淘汰
由于是数组,没有哈希索引,所有操作都是 O(N) 时间复杂度,适合小规模或教学演示:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
-
查找 key:遍历
keys[],比较是否 equals,返回下标或 -1 -
更新计数:找到下标 i 后,执行
counts[i]++ -
淘汰策略(LFU):遍历
counts[]找最小值;若多个最小值,建议淘汰 最早插入(下标最小) 的那个,以保持一定确定性(避免随机替换)
代码片段示意(无泛型简化版)
以下是一个极简核心逻辑示例:
立即学习“Java免费学习笔记(深入)”;
class SimpleLFUCache {
private final int capacity;
private final String[] keys;
private final String[] values;
private final int[] counts;
private int size;
public SimpleLFUCache(int capacity) {
this.capacity = capacity;
this.keys = new String[capacity];
this.values = new String[capacity];
this.counts = new int[capacity];
this.size = 0;
}
public String get(String key) {
for (int i = 0; i < size; i++) {
if (keys[i] != null && keys[i].equals(key)) {
counts[i]++;
return values[i];
}
}
return null;
}
public void put(String key, String value) {
// 先尝试更新已存在项
for (int i = 0; i < size; i++) {
if (keys[i] != null && keys[i].equals(key)) {
values[i] = value;
counts[i]++;
return;
}
}
// 新增:缓存未满,直接插入末尾
if (size < capacity) {
keys[size] = key;
values[size] = value;
counts[size] = 1;
size++;
return;
}
// 缓存已满:找 counts 最小且下标最小的位置替换
int minIdx = 0;
for (int i = 1; i < capacity; i++) {
if (counts[i] < counts[minIdx]) {
minIdx = i;
}
}
keys[minIdx] = key;
values[minIdx] = value;
counts[minIdx] = 1;
}
}
注意事项与局限
- 这不是严格 LRU,而是数组版 LFU(Least Frequently Used);真 LRU 需维护访问时序,常用链表+哈希表实现
- 数组查找慢,不适用于高并发或大数据量场景;生产环境推荐
LinkedHashMap(支持 access-order)或ConcurrentHashMap + 双向链表 - 若坚持在 LRU 中“加频率统计”,可额外用一个
Map<k integer></k>单独计数,但和 LRU 主逻辑解耦,不参与淘汰决策 - 注意 null 键/值处理、线程安全(本例非线程安全)、equals/hashCode 正确性(尤其 key 是自定义对象时)

















