package com.cause.hashmap;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
/**
* least frequency used 最少使用次数缓存淘汰策略
*/
public class LFUCache {
Map<Integer, Node> keyNodeMap = new HashMap();
Map<Integer, LinkedList<Node>> frequencyMap = new HashMap();
int capacity;
public LFUCache(int capacity) {
this.capacity = capacity;
}
public int get(int key) {
Node node = keyNodeMap.get(key);
if (node != null) {
updateFrequencyMap(node);
return node.value;
}
return -1;
}
// 更新节点访问频率
public void updateFrequencyMap(Node node) {
if (node == null) {
return;
}
// 更旧的链表
LinkedList<Node> oldList = frequencyMap.get(node.frequency);
if (oldList != null) {
if (oldList.size() > 1) {
oldList.remove(node);
} else {
// oldList.size 可能是1或者0
frequencyMap.remove(node.frequency);
}
}
// 更新新的链表
int newFrequency = node.frequency + 1;
node.frequency = newFrequency;
LinkedList<Node> newList = frequencyMap.getOrDefault(newFrequency, new LinkedList<>());
newList.add(node);
frequencyMap.put(newFrequency, newList);
}
public void put(int key, int value) {
// 如果超出了容量,同时以前没有存入,那就删除一个元素
if (keyNodeMap.size() >= capacity && !keyNodeMap.containsKey(key)) {
if (frequencyMap.keySet().size() > 0) {
// 获取最小频率
int minFrequency = Collections.min(frequencyMap.keySet());
LinkedList<Node> nodes = frequencyMap.get(minFrequency);
Node nodesFirst = nodes.getFirst();
if (nodes.size() > 1) {
nodes.removeFirst();
} else {
frequencyMap.remove(minFrequency);
}
keyNodeMap.remove(nodesFirst.key);
}
}
// 插入一个新的节点
if (keyNodeMap.size() <= capacity && capacity > 0) {
Node node;
if (keyNodeMap.containsKey(key)) {
node = keyNodeMap.get(key);
node.value = value;
} else {
node = new Node(key, value, 0);
keyNodeMap.put(key, node);
}
updateFrequencyMap(node);
}
}
class Node {
int key, value, frequency;
public Node(int key, int value, int frequency) {
this.key = key;
this.value = value;
this.frequency = frequency;
}
}
}
LFU缓存简洁的实现方式,思路清晰
最新推荐文章于 2024-10-31 15:57:13 发布