java实现LFU算法
简介
LFU(Least Frequently Used),即最不经常使用,淘汰一定时期内访问次数最少的元素,如果访问次数相同,则比较最新一次的访问时间。
代码实现1
复制import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class LFUCache<K, V> {
private int capacity;
private Map<K, CacheObject<V>> cache;
public LFUCache(int capacity) {
this.capacity = capacity;
cache = new HashMap<>(capacity);
}
public V get(K key) {
CacheObject<V> cacheObject = cache.get(key);
if (cacheObject == null) {
return null;
}
return cacheObject.getValue();
}
public void put(K key, V value) {
if (capacity == 0) {
return;
}
CacheObject<V> cacheObject = cache.get(key);
if (cacheObject == null) {
if (cache.size() >= capacity) {
//删除最少使用的键,使用次数相等,删除最久未使用的
cache.entrySet().stream()
.min(Comparator.comparing(Entry::getValue))
.ifPresent(e -> {
cache.remove(e.getKey());
});
}
cacheObject = new CacheObject<>(value);
} else {
cacheObject.setValue(value);
}
cache.put(key, cacheObject);
}
@Override
public String toString() {
return cache.toString();
}
static class CacheObject<V> implements Comparable<CacheObject<V>> {
private V value;
private long lastAccessTime;
private int accessCount;
CacheObject(V value) {
setValue(value);
}
V getValue() {
lastAccessTime = System.nanoTime();
accessCount++;
return value;
}
public void setValue(V value) {
this.value = value;
lastAccessTime = System.nanoTime();
accessCount++;
}
@Override
public String toString() {
return value + ":" + accessCount;
}
@Override
public int compareTo(CacheObject<V> o) {
int res = Integer.compare(this.accessCount, o.accessCount);
return res != 0 ? res : Long.compare(this.lastAccessTime, o.lastAccessTime);
}
}
}
存储被缓存对象的访问次数和最后访问时间,当缓存已经达到最大容量时,删除最少访问次数的数据,如果两个数据访问次数相等,删除最后访问时间久的数据。
代码实现2
复制import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;
class LFUCache2<K, V> {
private int capacity;
private Map<K, CacheObject<K, V>> cache;
private TreeSet<CacheObject<K, V>> treeSet;
public LFUCache2(int capacity) {
this.capacity = capacity;
cache = new HashMap<>(capacity);
treeSet = new TreeSet<>();
}
public V get(K key) {
CacheObject<K, V> cacheObject = cache.get(key);
if (cacheObject == null) {
return null;
}
treeSet.remove(cacheObject);
V value = cacheObject.getValue();
treeSet.add(cacheObject);
return value;
}
public void put(K key, V value) {
if (capacity == 0) {
return;
}
CacheObject<K, V> cacheObject = cache.get(key);
if (cacheObject == null) {
if (cache.size() >= capacity) {
//删除最少使用的键,使用次数相等,删除最久未使用的
cache.remove(treeSet.first().key);
treeSet.pollFirst();
}
cacheObject = new CacheObject<>(key, value);
} else {
treeSet.remove(cacheObject);
cacheObject.setValue(value);
}
treeSet.add(cacheObject);
cache.put(key, cacheObject);
}
@Override
public String toString() {
return cache.toString();
}
static class CacheObject<K, V> implements Comparable<CacheObject<K, V>> {
private K key;
private V value;
private long lastAccessTime;
private int accessCount;
CacheObject(K key, V value) {
this.key = key;
setValue(value);
}
V getValue() {
lastAccessTime = System.nanoTime();
accessCount++;
return value;
}
public void setValue(V value) {
this.value = value;
lastAccessTime = System.nanoTime();
accessCount++;
}
@Override
public String toString() {
return value + ":" + accessCount;
}
@Override
public int compareTo(CacheObject<K, V> o) {
int res = Integer.compare(this.accessCount, o.accessCount);
return res != 0 ? res : Long.compare(lastAccessTime, o.lastAccessTime);
}
}
}
相比第一种,使用TreeSet存储访问次数的顺序关系,可以很快的得到最不经常使用的数据。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 上周热点回顾(2.17-2.23)