LFU和LRU均是常见的缓存算法,其中LFU表示最不经常使用,LRU表示最近最少使用。
LRU (最近最少使用) 缓存机制要求支持以下操作: 获取数据 get 和 写入数据 put 。
LRUCache cache = new LRUCache( 2 /* 缓存容量 */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 该操作会使得密钥 2 作废
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 该操作会使得密钥 1 作废
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
public class LRU {
private int capacity;
private HashMap<Integer,Node> cache;
private Node head;
private Node tail;
public LRU(int capacity) {
this.capacity=capacity;
cache = new HashMap<>(capacity);
}
public int get(int key) {
if(capacity==0){
return -1;
}
Node node = cache.get(key);
if(node==null){
return -1;
}
recentUse(node);
return node.getValue();
}
private void recentUse(Node node) {
Node pre = node.getPre();
Node next = node.getNext();
if(pre==null){
return;
}
if(next!=null){
next.setPre(pre);
}
pre.setNext(next);
if(node==tail){
tail=pre;
}
node.setNext(head);
node.setPre(null);
head.setPre(node);
head = node;
}
public void put(int key, int value) {
if(capacity==0){
return;
}
Node node = cache.get(key);
if (node != null) {
node.setValue(value);
recentUse(node);
return;
}
node = new Node(key, value);
if (cache.size() == capacity) {
cache.remove(tail.getKey());
tail=tail.getPre();
if(tail!=null){
tail.setNext(null);
}
}
cache.put(key, node);
if(head!=null){
head.setPre(node);
}
node.setNext(head);
node.setPre(null);
head=node;
if(tail==null){
tail=node;
}
}
}
class Node{
private int key;
private int value;
private Node pre,next;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
public Node getPre() {
return pre;
}
public void setPre(Node pre) {
this.pre = pre;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
public int getKey() {
return key;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
最不经常使用(LFU)算法要求应支持以下两种操作:
LFUCache cache = new LFUCache( 2 /* capacity (缓存容量) */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 去除 key 2
cache.get(2); // 返回 -1 (未找到key 2)
cache.get(3); // 返回 3
cache.put(4, 4); // 去除 key 1
cache.get(1); // 返回 -1 (未找到 key 1)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
public class LFU {
private int capacity;
private int minFred;
private HashMap<Integer,Node> cache;
private HashMap<Integer, LinkedList<Node>> fredMap;
public LFU(int capacity) {
this.capacity=capacity;
cache = new HashMap<>(capacity);
fredMap = new HashMap<>();
minFred=0;
}
public int get(int key) {
if(capacity==0){
return -1;
}
Node node = cache.get(key);
if(node==null){
return -1;
}
fredIncrease(node);
return node.getValue();
}
private void fredIncrease(Node node) {
int fred = node.getFred();
LinkedList<Node> fredList = fredMap.get(fred);
fredList.remove(node);
if(node.getFred()==minFred&&fredList.isEmpty()){
minFred++;
}
fredList=fredMap.get(fred+1);
if(fredList==null||fredList.size()==0){
fredList=new LinkedList<>();
fredMap.put(fred+1,fredList);
}
fredList.addFirst(node);
node.fredInc();
}
public void put(int key, int value) {
if(capacity==0){
return;
}
Node node = cache.get(key);
if (node != null) {
node.setValue(value);
fredIncrease(node);
return;
}
node = new Node(key, value);
if (cache.size() == capacity) {
LinkedList<Node> fredList = fredMap.get(minFred);
Node last = fredList.removeLast();
cache.remove(last.getKey(),last);
}
cache.put(key, node);
LinkedList<Node> fredList = fredMap.get(0);
if (fredList == null) {
fredList = new LinkedList<>();
fredMap.put(0, fredList);
}
fredList.addFirst(node);
minFred = 0;
return;
}
public static void main(String[] args) {
LFU cache =new LFU(3);
cache.put(3, 1);
cache.put(2, 1);
System.out.println(cache.cache.keySet());
cache.put(2, 2);
System.out.println(cache.cache.keySet());
cache.put(4, 4);
System.out.println(cache.cache.keySet());
int res1 = cache.get(2);
System.out.println(res1);
int res2 = cache.get(3);
System.out.println(res2);
int res3 = cache.get(2);
System.out.println(res3);
int res4 = cache.get(1);
System.out.println(res4);
cache.put(5, 5);
int res5 = cache.get(1);
System.out.println(res5);
int res6 = cache.get(2);
System.out.println(res6);
int res7 = cache.get(3);
System.out.println(res7);
int res8 = cache.get(4);
System.out.println(res8);
int res9 = cache.get(5);
System.out.println(res9);
}
}
class Node{
private int key;
private int value;
private int fred = 0;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
public void setValue(int value) {
this.value = value;
}
public int getKey() {
return key;
}
public int getValue() {
return value;
}
public int getFred() {
return fred;
}
public void fredInc(){
fred++;
}
}