博客
关于我
LRU的map+双链表实现(Go描述)
阅读量:749 次
发布时间:2019-03-22

本文共 2669 字,大约阅读时间需要 8 分钟。

基于Map和双链表实现的LRU缓存算法

作者:lzw5399

日期:2021/5/20 22:28
描述:本文将介绍基于Map和双链表实现的LRU(最近使用)缓存算法的具体实现方式,详细阐述Set和Get操作的实现逻辑。

代码示例:

public class LRUCache {    private int capacity;    private Map
cache; private LinkedNode head; private LinkedNode tail; private ReentrantLock lock; public LRUCache(int capacity) { this.capacity = capacity; this.cache = new HashMap<>(); this.head = null; this.tail = null; this.lock = new ReentrantLock(); } public void set(int key, int value) { LinkedNode node = this.cache.get(key); if (node != null) { moveToFront(node); return; } if (capacity == cache.size()) { LinkedNode removed = removeTail(); this.cache.remove(removed.getKey()); } LinkedNode newNode = new LinkedNode(); newNode.key = key; newNode.value = value; addToFront(newNode); this.cache.put(key, newNode); } public int get(int key) { LinkedNode node = this.cache.get(key); if (node == null) { return -1; } moveToFront(node); return node.value; } private void moveToFront(LinkedNode node) { removeNode(node); addFront(node); } private LinkedNode removeTail() { if (tail.prev == null) { return tail; } LinkedNode removed = tail.prev; tail.prev.next = null; tail.prev = null; return removed; } private LinkedNode removeNode(LinkedNode node) { if (node.prev != null) { node.prev.next = node.next; } if (node.next != null) { node.next.prev = node.prev; } if (node.prev == null) { head = node.next; } if (node.next == null) { tail = node.prev; } return node; } private void addFront(LinkedNode node) { if (head == null) { head = tail = node; } else { node.prev = null; head.prev = node; } head = node; }}

代码说明:

  • 结构设计

    • LRUCache 类实现了一个基于Map和双链表的缓存机制,能够根据Least Recently Used(LRU)算法自动管理缓存空间。
    • 主要字段:
      • capacity:缓存的最大容量。
      • cache:存储缓存键值对的Map,同时每个键值对对应一个双链表节点。
      • headtail:双链表的头尾节点。
      • lock:用于保证多线程环境下的数据同步。
  • Set操作实现

    • set 方法用于将键值对加入缓存:
      • 检查是否存在相同的键,如果存在则将该节点移动到链表头部。
      • 如果不存在,检查缓存是否已满:
        • 满则移除链表尾部的节点,并删除Map中的对应记录。
        • 新增节点,插入链表头部,并将键值对加入Map。
  • Get操作实现

    • get 方法用于从缓存中获取指定键的值:
      • 检查是否存在对应的键,不存在则返回-1。
      • 存在则将该节点移动到链表头部,并返回对应的值。
  • 链表操作

    • moveToFront:将指定节点从当前位置移动到链表头部,需要先移除原有的位置,再插入头部。
    • removeTail:移除链表尾部的节点。
    • removeNode:移除指定节点,调整链表头部和尾部指针。
    • addFront:将节点插入链表头部,调整头部指针。
  • 这种设计保证了Set和Get操作的时间复杂度均为O(1),能够高效管理缓存。

    转载地址:http://qnkwk.baihongyu.com/

    你可能感兴趣的文章
    OSG学习:几何对象的绘制(三)——几何元素的存储和几何体的绘制方法
    查看>>
    OSG学习:几何对象的绘制(二)——简易房屋
    查看>>
    OSG学习:几何对象的绘制(四)——几何体的更新回调:旋转的线
    查看>>
    OSG学习:场景图形管理(一)——视图与相机
    查看>>
    OSG学习:场景图形管理(三)——多视图相机渲染
    查看>>
    OSG学习:场景图形管理(二)——单窗口多相机渲染
    查看>>
    OSG学习:场景图形管理(四)——多视图多窗口渲染
    查看>>
    OSG学习:新建C++/CLI工程并读取模型(C++/CLI)——根据OSG官方示例代码初步理解其方法
    查看>>
    Sql 随机更新一条数据返回更新数据的ID编号
    查看>>
    OSG学习:空间变换节点和开关节点示例
    查看>>
    OSG学习:纹理映射(一)——多重纹理映射
    查看>>
    OSG学习:纹理映射(七)——聚光灯
    查看>>
    OSG学习:纹理映射(三)——立方图纹理映射
    查看>>
    OSG学习:纹理映射(二)——一维/二维/简单立方图纹理映射
    查看>>
    OSG学习:纹理映射(五)——计算纹理坐标
    查看>>
    OSG学习:纹理映射(六)——灯光
    查看>>
    OSG学习:纹理映射(四)——三维纹理映射
    查看>>
    OSI七层模型的TCP/IP模型都有哪几层和他们的对应关系?
    查看>>
    OSM数据如何下载使用(地图数据篇.11)
    查看>>
    OSPF 四种设备角色:IR、ABR、BR、ASBR
    查看>>