緩存淘汰策略-LRU

LRU(Least Recently Used)

LRU 算法的設計原則是:如果一個數據在最近一段時間沒有被訪問到,那麼在將來它被訪問的可能性也很小。也就是說,當限定的空間已存滿數據時,應當把最久沒有被訪問到的數據淘汰。

提供一種基於map+鏈表的LRU緩存實現

public class LRUBaseHashMap {

    private HashMap<String, LRUNode> map;

    private int capacity;

    private LRUNode tail;

    private LRUNode head;

    public void set(String key, Object value) {
        LRUNode node = map.get(key);
        if (node != null) {
            // 原緩存已經存在了
            node.value = value;
            remove(node, false);
        } else {
            // 原緩存不存在
            node = new LRUNode(key, value);
            if (map.size() >= capacity) {
                //超出容量,淘汰過期緩存
                remove(tail, true);
            }
            map.put(key, node);
        }
        setHead(node);
    }

    public Object get(String key) {
        LRUNode node = map.get(key);
        if (node != null) {
            //最新讀取的緩存放到鏈表頭
            remove(node, false);
            setHead(node);
            return node.value;
        }
        return null;
    }

    public void del(String key) {
        LRUNode node = map.get(key);
        if (node != null) {
            remove(node, true);
        }
    }

    private void remove(LRUNode node, boolean remove) {
        if (node.prev != null) {
            node.prev.next = node.next;
        } else {
            head = node.next;
        }
        if (node.next != null) {
            node.next.prev = node.prev;
        } else {
            tail = node.prev;
        }
        node.next = null;
        node.prev = null;
        if (remove) {
            map.remove(node.key);
        }
    }

    private void setHead(LRUNode node) {
        if (head != null) {
            node.next = head;
            head.prev = node;
        }
        head = node;
        if (tail == null) {
            tail = node;
        }
    }

    public LRUBaseHashMap(int capacity) {
        this.capacity = capacity;
        this.map = new HashMap<>();
    }

    public static class LRUNode {
        public String key;
        public Object value;
        LRUNode prev;
        LRUNode next;

        public LRUNode(String key, Object value) {
            this.key = key;
            this.value = value;
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章