LRU最近最少使用策略

231 阅读1分钟
package com.algorithm.lru;

import java.util.HashMap;

/**
 * 简单LRU(最近最少使用)算法
 */
public class LRUCache<K, V> {

    private Node head, tail;

    private HashMap<K, Node> hashMap = new HashMap<>();

    private int size = 0;

    public int capacity = 10;

    public LRUCache() {
    }

    public LRUCache(int capacity) {
        this.capacity = capacity;
    }

    public void put(K key, V value) {
        Node node = hashMap.get(key);
        if (node != null) {
             node.value = value;
             if (node != head) {
                 if (node.next != null) {
                    node.prev.next = node.next;
                    node.next.prev = node.prev;
                 }else{
                     tail = node.prev;
                     tail.next = null;
                 }
                 node.prev = null;
                 node.next = head;
                 head.prev = node;
                 head = node;
             }
        }else{
            Node node1 = new Node();
            if (head == null && tail == null){
                head = tail = node1;
                head.key = key;
                head.value = value;
            }else{
                node.key = key;
                node.value = value;
                node.next = head;
                head.prev = node1;
                head = node1;
            }
            if (size + 1 <= capacity) {
                size ++;
            }else{
                Node newtail = tail.prev;
                tail.prev.next = null;
                tail.prev = null;
                tail = newtail;
            }
        }

    }

    public V get(K key) {
        // 遍历链表,找节点
        Node result = hashMap.get(key);
        // 找到节点且节点为非头结点
        if (result != null && result != head) {
            // 取出查询的节点,处理前后节点指针
            if (result.next != null) {
                result.next.prev = result.prev;
            } else {
                tail = tail.prev;
                tail.next = null;
            }
            result.prev.next = result.next;
            // 把取出的节点插入头结点
            result.next = head;
            head.prev = result;
            head = result;
            return result.value;
        }
        return null;
    }

    /**
     * 测试用的
     */
    public void show() {
        Node p = head;
        while (p != null) {
            System.out.printf("<%s,%s>", p.key, p.value);
            p = p.next;
        }
        System.out.println();
    }

    public class Node {
        Node prev,next;
        K key;
        V value;
    }
}