IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Java使用双向链表和哈希表实现LRU缓存 -> 正文阅读

[数据结构与算法]Java使用双向链表和哈希表实现LRU缓存

Java使用双向链表哈希表实现LRU缓存

  • getValue(Integer key):获取键对应的值,并标记最近使用过。
  • setKeyValue(Integer key, String value):将键值对插入到缓存,如果存在则删除旧的值。
  • removeKey(Integer key):将键值对从缓存中移除。
public class LRUCache {
	private Integer maxCacheSize;
	private Map<Integer, DoubleListNode> map;
	private DoubleListNode head;
	private DoubleListNode tail;

	public LRUCache(Integer maxCacheSize) {
		this.maxCacheSize = maxCacheSize;
		this.map = new HashMap<>();
	}

	/**
	 * 获取键对应的值,并标记最近使用过
	 *
	 * @param key
	 * @return
	 */
	public String getValue(Integer key) {
		DoubleListNode node = map.get(key);
		if (node == null) {
			return null;
		}
		// 移动到链表头部并标记最近使用过
		if (node != head) {
			// 从链表中移除节点
			removeFromLinkedList(node);
			// 插入到链表头部
			insertAtFrontOfLinkedList(node);
		}
		return node.value;
	}

	/**
	 * 将键值对插入到缓存,如果存在则删除旧的值
	 *
	 * @param key
	 * @param value
	 */
	public void setKeyValue(Integer key, String value) {
		// 如果存在则删除旧的值
		removeKey(key);

		// 如果元素数目超过缓存最大容量,则移除 最近最少使用 的元素(最久没有使用的元素)
		if (map.size() >= maxCacheSize && tail != null) {
			// 移除 最近最少使用 的元素(最近最少使用的元素位于链表尾部)
			removeKey(tail.key);
		}

		// 将键值对插入到缓存
		DoubleListNode node = new DoubleListNode(key, value);
		insertAtFrontOfLinkedList(node);
		map.put(key, node);
	}

	/**
	 * 将键值对从缓存中移除,即从链表和散列表中都移除
	 *
	 * @param key
	 */
	public void removeKey(Integer key) {
		DoubleListNode node = map.get(key);
		// 从链表中移除
		removeFromLinkedList(node);
		// 从散列表中移除
		map.remove(key);
	}

	/**
	 * 从链表中移除节点
	 *
	 * @param node
	 */
	private void removeFromLinkedList(DoubleListNode node) {
		if (node == null) {
			return;
		}
		// 如果node存在前驱节点,让前驱节点的后继指向node的后继节点
		if (node.pre != null) {
			node.pre.next = node.next;
		}
		// 如果node存在后继节点,让后继节点的前驱指向node的前驱节点
		if (node.next != null) {
			node.next.pre = node.pre;
		}
		// 如果删除的是尾节点,需要将tail前移
		if (node == tail) {
			tail = node.pre;
		}
		// 如果删除的是头节点,需要将head后移
		if (node == head) {
			head = node.next;
		}
	}

	/**
	 * 在链表头部插入节点
	 *
	 * @param node
	 */
	private void insertAtFrontOfLinkedList(DoubleListNode node) {
		// 要将node指针清空,否则会导致错误链接
		node.pre = node.next = null;
		// 当前没有节点
		if (head == null) {
			head = node;
			tail = node;
		} else {
			// 头节点的前驱指向node
			head.pre = node;
			// node的后继指向头节点
			node.next = head;
			// head指向node,更新头节点
			head = node;
		}
	}

	static class DoubleListNode {
		private Integer key;
		private String value;
		private DoubleListNode next, pre;

		public DoubleListNode(Integer key, String value) {
			this.key = key;
			this.value = value;
		}
	}
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-08-24 15:48:54  更:2021-08-24 15:49:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:44:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码