如何实现最不常用 (LFU) 缓存?

2022-09-01 17:38:05

最不常用 (LFU) 是一种用于管理计算机内存的缓存算法。此方法的标准特征涉及系统跟踪块在内存中引用的次数。当缓存已满并需要更多空间时,系统将以最低的参考频率清除项目。

实现最近使用的对象缓存的最佳方式是什么,例如在Java中?

我已经使用LinkedHashMap实现了一个(通过维护no。访问对象的时间)但我很好奇是否有任何新的并发集合会是更好的候选者。

考虑这种情况:假设缓存已满,我们需要为另一个缓存腾出空间。假设缓存中记录了两个对象,它们仅被访问一次。如果我们知道另一个(不在缓存中)对象被访问了不止一次,那么要删除哪一个?

谢谢!


答案 1

您可能会从 ActiveMQ: LFUCache 的 LFU 实现中受益

它们提供了一些很好的功能。


答案 2

我认为,LFU数据结构必须结合优先级队列(用于维护对lfu项目的快速访问)和哈希映射(用于通过其键提供对任何项目的快速访问);我建议为缓存中存储的每个对象使用以下节点定义:

class Node<T> {
   // access key
   private int key;
   // counter of accesses
   private int numAccesses;
   // current position in pq
   private int currentPos;
   // item itself
   private T item;
   //getters, setters, constructors go here
}

您需要引用项目。您需要作为优先级队列的键。您需要能够通过键快速找到项目的pq位置。现在,您组织哈希映射 (key() -> node()) 以快速访问项目,并使用访问次数作为优先级来最小基于堆的优先级队列。现在,您可以非常快速地执行所有操作(访问,添加新项目,更新访问次数,删除lfu)。您需要仔细编写每个操作,以便它保持所有节点的一致性(它们的访问次数,它们在pq中的位置以及在哈希映射中存在)。所有操作都将以恒定的平均时间复杂度工作,这是您对缓存的期望。keynumAccessescurrentPosIntegerNode<T>