我正在使用我自己的DoublyLinkedList实现来实现LRU缓存,其中一个节点具有整数键和值,其中键表示页面标识符,值表示它在磁盘上的位置。此外,我正在使用Hashmap进行O(1)访问。我知道以下实施基础知识:
如果请求的密钥是缓存命中,则返回其值(即其位置)并将此节点移动到DoublyLinkedList的前面。
我怀疑是另一个重要的方面。根据各种资源,当它是一个未命中时,那么在我的情况下作为键的页码被设置为LinkedList的头部,并且在这样做时,如果我们遇到满的容量,那么我们删除最后的元素然后把它输到前面。现在出于实现的目的,当我将它带入缓存时,这个页码(即密钥)的“值”是什么?我应该把它设置成垃圾吗?在我下面介绍的'get'方法的实现中,我目前正在返回-1。
此外,在LRU缓存的实际生产代码中,缓存是否包含存储在这些页码中的页码或实际值? Ť
请帮我澄清这个方面。感谢。
import java.util.HashMap;
public class LRU {
private static class Node {
Node previous;
Node next;
int key;
int value;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
}
Node head = null;
Node tail = null;
HashMap<Integer, Node> hmap = new HashMap<>();
public int get(int key) {
if (hmap.containsKey(key)) {
Node n = hmap.get(key);
remove(n);
moveToFront(n);
return n.value;
}
return -1;
}
public void remove(Node n) {
// if n is head
if (n.previous == null) {
head = head.next;
} else {
n.previous.next = n.next;
}
//if n is tail
if (n.next == null) {
tail = n.previous;
} else {
n.next.previous = n.previous;
}
}
public void moveToFront(Node n) {
if(n==head)
return;
if(n.next==null)
{
n.previous.next=n.next;
tail = n.previous;
n.previous = null;
n.next = head;
head = n;
}
else {
n.previous.next=n.next;
n.next.previous=n.previous;
}
}
public void set(int key, int value) {
}
}
答案 0 :(得分:0)
术语缓存通常标识具有有限容量的键值对映射。在达到容量时尝试添加新对将导致其中一个现有键值对被逐出,并且新增一个键值对。通常,添加一对作为尝试检索当前未存储在缓存中的密钥的值的函数隐式发生(即缓存执行驱逐,加载新对,并返回值)。 p>
LRU(最近最少使用)是选择被驱逐对的可能政策之一,而不是唯一的政策。处理器数据高速缓存是以硬件实现的高速缓存的示例,其中密钥是从地址获得的(通常仅考虑一定数量的最高有效位),并且该值是包含这种地址的存储器的一部分。例如,缓存行包含驻留在内存中的数据的副本。 另一个例子是,在支持虚拟存储器的OS中,OS分页被实现为OS内核中的HW(MMU)和软件的组合。在此示例中,更接近您描述的内容,该对的值是托管虚拟页面的内存页面的物理地址。
所以当你问“另外,在LRU缓存的实际生产代码中,缓存是否包含存储在那些页码的页码或实际值?T”时,答案可能取决于我们所讨论的缓存。在您的情况下,不清楚缓存是由什么支持的。我会假设它是某个文件中的偏移量。在这种情况下,我希望您的值是一个字节数组或表示文件一部分的字符串。对文件中偏移x的访问将映射到key = offset / PAGE_SIZE;如果表中没有密钥,并且表是否有容量,那么最后一个节点可以“循环”,设置替换现有密钥,在偏移处读取文件内容(key,key + PAGE_SIZE-1) )在字节缓冲区中,最后移动页面。