LRU(Least recently used,最近最少使用)
java简单实现: import java.util.HashMap;
class Node{
public Node(String key,String value){
this.key = key;
this.value = value;
}
public Node pre;
public Node next;
public String key;
public String value;
}
public class LRUCache {
private Node head;
private Node end;
//缓存上限
private int limit;
private HashMap map;
public LRUCache(int limit) {
this.limit = limit;
map = new HashMap();
}
public String get(String key) {
Node node = map.get(key);
if(node == null) {
return null;
}
//调整node到尾部
refreshNode(node);
return node.value;
}
public void put(String key, String value) {
Node node = map.get(key);
if(node == null) {
//key不存在直接插入
while(map.size() >= limit) {
//去除链表内的节点
String oldKey = removeNode(head);
//去除map中的缓存
map.remove(oldKey);
}
node = new Node(key, value);
//链表中加入节点
addNode(node);
//map中加入节点
map.put(key, node);
} else {
//更新节点并调整到尾部
node.value = value;
refreshNode(node);
}
}
private void refreshNode(Node node) {
//如果访问的是尾节点,无须移动节点
if(node == end) {
return;
}
//把节点移动到尾部,相当于做一次删除插入操作
removeNode(node);
addNode(node);
}
private String removeNode(Node node) {
//尾节点
if(node == end) {
end = end.pre;
} else if(node == head) {
//头结点
head = head.next;
} else {
//中间节点
node.pre.next = node.next;
node.next.pre = node.pre;
}
return node.key;
}
private void addNode(Node node) {
if(end != null) {
end.next = node;
node.pre = end;
node.next = null;
}
end = node;
if(head == null) {
head = node;
}
}
}
另外,通常不需要我们自己专门实现一个此算法的数据结构,使用java内置的LinkedHashMap定制即可。
通过查看LinkedHashMap源码会发现构造函数默认有一个accessOrder = false;。
官方对他的注释是The iteration ordering method for this linked hash map: true for access-order, false for insertion-order.,意思是“对于此linked hash map的迭代排序而言,accessOrder是true的话,按照访问顺序存储,accessOrder是false的话,按照插入顺序存储”。
所以我们只要使用下面这个构造函数,就可以使得LinkedHashMap按照访问顺序构造双向链表 public LinkedHashMap(int initialCapacity, float loadFactor,
boolean accessOrder) {
super(initialCapacity, loadFactor);
this.accessOrder = accessOrder;
}
要想让LinkedHashMap实现LRU,还必须让LinkedHsahMap有一个存储阈值,也就是重写下面这个方法:
protected boolean removeEldestEntry(Map.Entry eldest) {
return false;
}
这个方法的注释有这么一段话:
/**
* Sample use: this override will allow the map to grow up to 100
* entries and then delete the eldest entry each time a new entry is
* added, maintaining a steady state of 100 entries.
* private static final int MAX_ENTRIES = 100;
* protected boolean removeEldestEntry(Map.Entry eldest) {
* return size() > MAX_ENTRIES;
* }
*/
一目了然了,所以一般只要这么写就可以实现LRU: public class LRUCache extends LinkedHashMap {
private final int MAX_CACHE_SIZE;
public LRUCache2(int ***Size) {
super((int) Math.ceil(***Size / 0.75) + 1, 0.75f, true);
MAX_CACHE_SIZE = ***Size;
}
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > MAX_CACHE_SIZE;
}
}
就这样吧……感觉像写了一篇简易博客