Java基於散列表的LRU算法

import java.util.HashMap;

/**
 * @Description:基於散列表的LRU算法
 */
public class LRUBaseHashTable<K, V> {

    /**
     * 默認鏈表容量
     */
    private final static Integer DEFAULT_CAPACITY = 10;

    /**
     * 頭結點
     */
    private DNode<K, V> headNode;

    /**
     * 尾節點
     */
    private DNode<K, V> tailNode;

    /**
     * 鏈表長度
     */
    private Integer length;

    /**
     * 鏈表容量
     */
    private Integer capacity;

    /**
     * 散列表存儲key
     */
    private HashMap<K, DNode<K, V>> table;

    /**
     * 雙向鏈表
     */
    static class DNode<K, V> {

        private K key;

        /**
         * 數據
         */
        private V value;

        /**
         * 前驅指針
         */
        private DNode<K, V> prev;

        /**
         * 後繼指針
         */
        private DNode<K, V> next;

        DNode() {
        }

        DNode(K key, V value) {
            this.key = key;
            this.value = value;
        }

    }

    public LRUBaseHashTable(int capacity) {
        this.length = 0;
        this.capacity = capacity;

        headNode = new DNode<>();

        tailNode = new DNode<>();

        headNode.next = tailNode;
        tailNode.prev = headNode;

        table = new HashMap<>();
    }

    public LRUBaseHashTable() {
        this(DEFAULT_CAPACITY);
    }

    /**
     * 新增
     *
     * @param key
     * @param value
     */
    public void add(K key, V value) {
        DNode<K, V> node = table.get(key);
        if (node == null) {
            DNode<K, V> newNode = new DNode<>(key, value);
            table.put(key, newNode);
            addNode(newNode);

            if (++length > capacity) {
                DNode<K, V> tail = popTail();
                table.remove(tail.key);
                length--;
            }
        } else {
            node.value = value;
            moveToHead(node);
        }
    }

    /**
     * 將新節點加到頭部
     *
     * @param newNode
     */
    private void addNode(DNode<K, V> newNode) {
        newNode.next = headNode.next;
        newNode.prev = headNode;

        headNode.next.prev = newNode;
        headNode.next = newNode;
    }

    /**
     * 彈出尾部數據節點
     */
    private DNode<K, V> popTail() {
        DNode<K, V> node = tailNode.prev;
        removeNode(node);
        return node;
    }

    /**
     * 移除節點
     *
     * @param node
     */
    private void removeNode(DNode<K, V> node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    /**
     * 將節點移動到頭部
     *
     * @param node
     */
    private void moveToHead(DNode<K, V> node) {
        removeNode(node);
        addNode(node);
    }

    /**
     * 獲取節點數據
     *
     * @param key
     * @return
     */
    public V get(K key) {
        DNode<K, V> node = table.get(key);
        if (node == null) {
            return null;
        }
        moveToHead(node);
        return node.value;
    }

    /**
     * 移除節點數據
     *
     * @param key
     */
    public void remove(K key) {
        DNode<K, V> node = table.get(key);
        if (node == null) {
            return;
        }
        removeNode(node);
        length--;
        table.remove(node.key);
    }

    private void printAll() {
        DNode<K, V> node = headNode.next;
        while (node.next != null) {
            System.out.print(node.value + ",");
            node = node.next;
        }
        System.out.println();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章