LRU(最近最少)

LRU是什么?按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非常著名的计算机操作系统基础理论得来的:最近使用的页面数据会在未来一段时期内仍然被使用,已经很久没有使用的页面很有可能在未来较长的一段时间内仍然不会被使用。基于这个思想,会存在一种缓存淘汰机制,每次从内存中找到最久未使用的数据然后置换出来,从而存入新的数据!它的主要衡量指标是使用的时间,附加指标是使用的次数。在计算机中大量使用了这个机制,它的合理性在于优先筛选热点数据,所谓热点数据,就是最近最多使用的数据!因为,利用LRU我们可以解决很多实际开发中的问题,并且很符合业务场景。

下面是完整的lru算法实现示例:

package cn.liu.demo.algorithm;

import cn.hutool.core.util.ObjectUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class LRU<K,V> {
    /**
     * 采用双向链表进行存储,采用hashmap进行查找
     */
    private HashMap<K,Node> hashMap;

    //头指针
    private Node head;

    //尾指针
    private Node tail;

    public LRU(){
        hashMap=new HashMap<>();
    }

    public List<Node> get(){
        List<Node> nodes=new ArrayList<>();
        if(ObjectUtil.isEmpty(hashMap)){
            return nodes;
        }
        Node first=head;
        if(ObjectUtil.isEmpty(first)){
            return nodes;
        }
        while (first!=null){
            nodes.add(first);
            first=first.nextNode;
        }
        return nodes;
    }

    //插入数据 采用头插法
    public void put(K key,V value){
        //判断key是否存在
        Node node=hashMap.get(key);
        if(ObjectUtil.isEmpty(node)){
            //不存在,创建新的节点插入
            node=new Node(key,value);
        }
        node.value=value;
        moveToHead(node);
        hashMap.put(key,node);
    }


    public void remove(K key){
        Node node=hashMap.get(key);
        if(ObjectUtil.isEmpty(node)){
            return;
        }
        deleteNode(node);
        hashMap.remove(key);
    }

    private void deleteNode(Node node){
        //头节点移除
        if(head.key.equals(node.key)){
            Node next=head.nextNode;
            head.nextNode=null;
            head=next;
            head.preNode=null;
            return;
        }
        //尾节点移除
        if(tail.key.equals(node.key)){
            Node pre=tail.preNode;
            tail.preNode=null;
            tail=pre;
            tail.nextNode=null;
            return;
        }
        Node preNode=node.preNode;
        Node nextNode=node.nextNode;
        preNode.nextNode=nextNode;
        nextNode.preNode=preNode;
    }

    //头插法
    private void moveToHead(Node node){
        if(ObjectUtil.isEmpty(head) || ObjectUtil.isEmpty(tail)){
            //将当前新的节点当做第一个节点
            head=tail=node;
            return;
        }
        if(ObjectUtil.isEmpty(head.nextNode)){
            head.preNode=node;
            node.nextNode=head;
            head=node;
            return;
        }

        if(head.key.equals(node.key)){
            //当前移动的节点已在最前面,不需要移动
            return;
        }

        //如果移动的是尾节点
        if(tail.key.equals(node.key)){
            tail=node.preNode;
        }

        //将已经存在的节点移动到头节点
        if(ObjectUtil.isNotEmpty(node.preNode)){
            node.preNode.nextNode=node.nextNode;

        }

        if(ObjectUtil.isNotEmpty(node.nextNode)){
            node.nextNode.preNode=node.preNode;
        }

        head.preNode=node;
        node.nextNode=head;
        head=node;
        head.preNode=null;


    }

    public static void main(String[] args) {
        LRU<Integer,String> lru=new LRU<>();
        lru.put(1,"11");
        lru.put(2,"22");
        lru.put(3,"33");
        lru.put(4,"44");
        lru.put(2,"22");
        lru.put(1,"11");
        lru.put(3,"33");
        lru.put(3,"33");
        lru.put(4,"44");
        lru.put(1,"11");
        System.out.println("插入前======");
        lru.print(lru);

        lru.remove(4);
        System.out.println("删除后======");
        lru.print(lru);

    }

    private void print(LRU<K,V> lru){
        List<Node> nodes=lru.get();
        nodes.forEach(node -> {
            System.out.print(node.key+"->");
        });
        System.out.println("");
    }

}

class Node{
    Node preNode;

    Object key;

    Object value;

    Node nextNode;

    Node(Object key,Object value){
        this.key=key;
        this.value=value;
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值