LRU(缓存淘汰算法)-基于哈希链表的方式

基于哈希链表的方式实现的LRU算法,通过Hash表存储加快数据的访问效率

节点类

package demo.LRU2;

/**
 * @author koala
 * @ClassName Node
 * @date 2019/9/17 09:24
 * @Description
 * @Version V1.0
 */

public class Node {

    String key;
    Object value;


    /**
     * 上一个节点
     */
    Node preNode;

    /**
     * 下一个节点
     */
    Node nextNode;

    /**
     * 构造方法
     * @param key
     * @param value
     */
    Node(String key,Object value){
        this.key = key;
        this.value = value;

        this.preNode = null;
        this.nextNode = null;
    }



    @Override
    public String toString() {
        return super.toString();
    }
}

双向链表类

这里的双向链表只存储头部节点和尾部节点;

package demo.LRU2;

/**
 * @author koala
 * @ClassName DoublyLinkedList
 * @date 2019/9/17 10:09
 * @Description 双向链表
 * @Version V1.0
 */

public class DoublyLinkedList {

    public Node head;
    public Node tail;


    DoublyLinkedList(){
        this.head = null;
        this.tail = null;
    }


    /**
     * 移动到头部节点去
     * @param node
     */
    public void moveToHead(Node node){


        if(node == null || node == head){
            return ;
        }

        // 如果当前节点是尾节点;
        if(tail == node){
            // 把当前节点添加到头部去
            addToHead(node);
            // 移除尾部的节点
            removeTail();
        }else{


            // 当前节点前后节点交换
            Node curNextNode =  node.nextNode;
            curNextNode.preNode = node.preNode;

            Node curPreNode = node.preNode;
            curPreNode.nextNode = curNextNode;



            // 节点交换
            head.preNode = node;

            node.nextNode = head;

            node.preNode = null;

            head = head.preNode;
        }

    }


    /**
     *  删除尾部节点
     */
    public Node removeTail(){
        if(tail == null){
            return null;
        }

        /**
         * 获取当前尾部节点;
         */
        Node n = tail;
        if(head == tail){
            head = null;
            tail = null;
        }else{
            // 当前尾部节点的上一个节点就为新的尾节点
             tail =  n.preNode;
             // 尾节点的下一个节点置空
             tail.nextNode = null;
        }
        //
        return n;
    }


    /**
     *
     * @param node
     */
    public void addToHead(Node node){

        if(node == null){
            return ;
        }

        /**
         * 如果没有上一级节点,证明是第一个节点,那假定前一个和后一个节点都是当前节点
         */
        if(head == null){
            head = node;
            tail = node;
        }else{
            // 把当前节点放到链表最前面
            node.nextNode = head;
            head.preNode = node;

            // 重新指定头部节点
            head = node;
        }
    }


    @Override
    public String toString() {
        return super.toString();
    }
}


缓存类

package demo.LRU2;

import java.util.HashMap;
import java.util.Map;

/**
 * @author koala
 * @ClassName Cache
 * @date 2019/9/17 09:23
 * @Description
 * 最近最少使用算法 。 最近最少使用的元素,在接下来一段时间内,被访问的概率也很低。
 *  * 即最近被使用的元素,在接下来一段时间内,被访问概率较高。
 *  * 

* * 用链表的结构: * * 链表头部表示最后实现的数据,越靠近最后表示没有使用的数据; * *

* 插入一个元素,如果没有达到阈值,就放到最前面;如果超过最大的阈值,移除链表尾部的数据; * * * * 访问一个元素,如果存在,则将该元素放到最前面;如果不存在;则返回空 * *

* * * 为提高效率,采用hash表存储数据 * @Version V1.0 */ public class Cache { private HashMap map; /** * 双向链接实现LRU顺序 */ private DoublyLinkedList list; /** * 当前节点的大小 */ private int size = 0; /** * 最大容量 */ private int capacity = 10; /** * 初始化、并且赋值最大的容量 * @param capacity */ Cache(int capacity){ this.list = new DoublyLinkedList(); this.map = new HashMap<>(); this.capacity = capacity; } Cache(){ this.list = new DoublyLinkedList(); this.map = new HashMap<>(); } /** * 插入一个数据 * @param key */ public void put(String key,Object value){ if(!map.containsKey(key)){ Node n = new Node(key,value); map.put(key,n); list.addToHead(n); // 如果超过最大的容量、移除最后一个数据 if(map.size() > capacity){ Node node = list.removeTail(); map.remove(node.key); } }else{ // 如果存在,就覆盖value的值 Node node = map.get(key); node.value = value; list.moveToHead(node); } } /** * 根据键获取值 * @param key * @return */ public Object get(String key){ if(map.containsKey(key)){ Node node = map.get(key); list.moveToHead(node); return node.value; }else{ return null; } } public DoublyLinkedList getAllList(){ return list; } public Map getAllDataMap(){ return this.map; } }

测试类

package demo.LRU2;


/**
 * @author koala
 * @ClassName test
 * @date 2019/9/17 10:55
 * @Description
 * @Version V1.0
 */

public class test {


    public static void main(String[] args) {



        Cache cache = new Cache(5);

        cache.put("1","hello1");
        cache.put("2","hello2");
        cache.put("3","hello3");
        cache.put("4","hello4");
        cache.put("5","hello5");
        cache.put("6","hello6");

        cache.get("3");


        for (Object map:cache.getAllDataMap().entrySet()) {
            System.out.println(map.toString());
        }

        DoublyLinkedList doublyLinkedList =   cache.getAllList();

        System.out.println(doublyLinkedList.head.preNode);
        System.out.println(doublyLinkedList.tail);

        System.out.println("头部节点, key:"+doublyLinkedList.head.key+";" +
                "头部节点上级节点:"+doublyLinkedList.head.preNode+"" +
                "头部节点下级节点:"+doublyLinkedList.head.nextNode.key);

        System.out.println("尾部节点, key:"+doublyLinkedList.tail.key+";" +
                "尾部节点上级节点:"+doublyLinkedList.tail.preNode.key+"" +
                "尾部节点下级节点:"+doublyLinkedList.tail.nextNode);

    }
}

计算结果

LRU(缓存淘汰算法)-基于哈希链表的方式_第1张图片

你可能感兴趣的:(LRU,缓存淘汰算法,算法)