LRUアルゴリズムを手書き


LRU(Least Recently Used)アルゴリズムの概要
最近最も長い間使用されていないポリシーでは、最も長い間使用されていないデータ、つまり前回アクセスされた時間が現在最も長いデータを優先的に淘汰します.このアルゴリズムは、メモリ(キャッシュ)のデータがホットスポットデータであることを保証し、キャッシュヒット率を保証します.
アルゴリズム実装
思想:LRUのアルゴリズム思想によると、双方向チェーンテーブルをキャッシュとして私たちのデータを格納することができ、あるデータにアクセスするたびに、このノードを元の位置から削除し、チェーンテーブルのヘッダに挿入することができ、チェーンテーブルの末尾に最近最も長く使用されていないノードが格納されていることを保証することができる.ノード数がキャッシュ容量を超えると、末尾のノードが削除されます.質問:これでは、チェーンテーブル内のノードが秩序正しく遍歴できることを知っているため、時間の複雑さが高くなります.このように時間の複雑さはO(n)であり,これは受け入れられないので,例えばHashMapを用いてすべてのノードを格納する方法を考えることができる.これにより,検索時にはO(1)時間だけでターゲットノードを得ることができる.また、双方向チェーンテーブルを使用しているので、ターゲットノードを簡単に削除し、左右を接続することができます.
コード:
テストクラス:
public class LRUTest {
    public static void main(String[] args) {
        LUR lur = new LUR<>(4);
        for (int i =0;i<10;i++){
            lur.put(i,i);
        }
    }
}

実装:

import java.util.HashMap;
import java.util.Iterator;

public class LUR implements Iterable {
    private Node head;
    private Node tail;
    private HashMap map;
    private int maxSize;

    private class Node {
        Node pre;
        Node next;
        K k;
        V v;

        public Node(K k, V v) {
            this.k = k;
            this.v = v;
        }
    }

    public LUR(int maxSize) {
        this.maxSize = maxSize;
        this.map = new HashMap<>(maxSize * 4 / 3);
        head = new Node(null, null);
        tail = new Node(null, null);
        head.next = tail;
        tail.pre = head;
    }

    public V get(K key) {
        if (!map.containsKey(key)) {
            return null;
        }
        Node node = map.get(key);
        unlink(node);
        appendHead(node);
        System.out.println("    :" + node.k);
        return node.v;
    }

    public void put(K key, V value) {
        if (map.containsKey(key)) {
            Node node = map.get(key);
            unlink(node);
        }
        Node node = new Node(key, value);
        map.put(key, node);
        appendHead(node);
        System.out.println("    :" + node.k);
        if (map.size() > maxSize) {
            Node toRemove = removeTail();
            System.out.println("    :" + toRemove.k);
            map.remove(toRemove.k);
        }
    }

    private Node removeTail() {
        Node node = tail.pre;
        Node pre = node.pre;
        tail.pre = pre;
        pre.next = tail;
        node.next = null;
        node.pre = null;
        return node;
    }

    private void appendHead(Node node) {
        Node next = head.next;
        node.next = next;
        next.pre = node;
        node.pre = head;
        head.next = node;
    }

    private void unlink(Node node) {
        Node pre = node.pre;
        Node next = node.next;
        pre.next = next;
        next.pre = pre;

        node.pre = null;
        node.next = null;
    }


    @Override
    public Iterator iterator() {
        return new Iterator() {
            private Node curr = head.next;

            @Override
            public boolean hasNext() {
                return curr != tail;
            }

            @Override
            public K next() {
                Node node = curr;
                curr = curr.next; //      。   
                return node.k;
            }
        };
    }
}