算法008:LRU算法实现:双向链表+HashMap 实现LRU算法,不允许用LinkedHashMap

160 阅读1分钟
题目:
LRUTest:Least Recently Used get put
pot ,get方法的书写
LRU算法实现:双向链表+HashMap 实现LRU算法,不允许用LinkedHashMap

思路:
热点元素在前,冷元素在后,会被淘汰掉

1.代码如下

1.1LRU.java:

package com.yuhl;

import java.util.HashMap;

/**
 * @author yuhl
 * @Date 2020/10/24 22:43
 * @Classname LRUTest
 * @Description LRUTest:Least Recently Used get put
 * pot ,get方法的书写
 * LRU算法实现:双向链表+HashMap 实现LRU算法,不允许用LinkedHashMap
 */
public class LRU {


    /**
     * Node节点定义
     */
    class Node{
        int key;
        int value;
        Node pre;
        Node next;
    }

    public HashMap<Integer,Node> hashMap ;
    public Node head;
    public Node tail;
    public int capacity;
    public int size;

    public LRU(int capacity) {
        this.head = new Node();
        this.tail = new Node();
        this.hashMap = new HashMap<>();
        this.head.next = tail;
        this.tail.pre = head;
        this.capacity = capacity;
        this.size = 0;
    }

    // 热点数据使用时插入头部
    public void addNode(Node node){
        node.pre = this.head;
        node.next = this.head.next;

        this.head.next.pre = node;
        this.head.next = node;
    }

    // 冷的放在链表末尾
    public void moveToHead(Node node){
        removeNode(node);
        addNode(node);
    }

    //删除node
    public void removeNode(Node node){
        node.pre.next = node.next;
        node.next.pre = node.pre;
    }

    //删除并返回最后一个元素
    public Node popTail(){
        Node res = this.tail.pre;
        removeNode(this.tail.pre);
        return res;
    }

    //放入元素
    public void put(int key,int value){
        Node node = new Node();
        node.key = key;
        node.value = value;

        Node oldNode = this.hashMap.get(key);
        // 不存在key重复
        if(oldNode == null){
            addNode(node);
            this.hashMap.put(key,node);

            // 插入后判断大小 超出则将最老的节点移除
            if(++this.size>capacity){
                Node tail = popTail();
                this.hashMap.remove(tail.key);
                size --;
            }
        }else{
            // 更新值,并设置到头
            oldNode.value = value;
            moveToHead(oldNode);
        }
    }

    public int get(int key){
        Node node = this.hashMap.get(key);
        if(node == null) return -1;
        moveToHead(node);
        return node.value;
    }
}

1.2LRUTest.java:测试类

package com.yuhl;

import java.util.HashMap;

/**
 * @author yuhl
 * @Date 2020/10/24 23:02
 * @Classname LRUTest
 * @Description 测试LRU算法
 * 当 5加入后被挤出去了
 */
public class LRUTest {
    public static void main(String[] args) {
        LRU lru = new LRU(4);
        lru.put(1,1);
        lru.put(2,2);
        lru.put(3,3);
        lru.put(4,4);
        lru.put(5,5);
        int i = lru.get(4);
        System.out.println(i);

        System.out.println(lru.hashMap);//5加入后被挤出去了
    }
}

2.执行结果:

"C:\Program Files\Java\jdk1.8.0_201\bin\java.exe" 
4
{2=com.yuhl.LRU$Node@1b6d3586, 3=com.yuhl.LRU$Node@4554617c, 4=com.yuhl.LRU$Node@74a14482, 5=com.yuhl.LRU$Node@1540e19d}