当前位置: 首页 > wzjs >正文

企业数据查询网站又一病毒来了比新冠可怕

企业数据查询网站,又一病毒来了比新冠可怕,河北邢台疫情最新消息今天,网站开发流行语言深入理解缓存淘汰算法:LRU与LFU实现原理与代码详解 一、缓存淘汰算法概述 缓存淘汰算法是计算机科学中用于管理有限缓存空间的重要策略。当缓存空间不足时,这些算法决定哪些数据应该被保留,哪些应该被淘汰。最常见的两种淘汰算法是&#xf…

深入理解缓存淘汰算法:LRU与LFU实现原理与代码详解

一、缓存淘汰算法概述

缓存淘汰算法是计算机科学中用于管理有限缓存空间的重要策略。当缓存空间不足时,这些算法决定哪些数据应该被保留,哪些应该被淘汰。最常见的两种淘汰算法是:

  • LRU (Least Recently Used):最近最少使用算法
  • LFU (Least Frequently Used):最不经常使用算法

二、LRU缓存实现详解

1. 核心思想

LRU基于"最近最少使用"原则淘汰数据,通过维护访问顺序来实现。

2. 完整实现代码

import java.util.LinkedList;
import java.util.HashMap;
import java.util.Map;class LRUCache {// 使用双向链表维护访问顺序(最近访问的键位于头部)private final LinkedList<Integer> accessOrder;// 使用HashMap存储键值对,实现O(1)时间复杂度的访问private final Map<Integer, Integer> cacheMap;// 缓存容量(final修饰,确保不可变)private final int capacity;/*** 构造函数,初始化缓存容量和数据结构* @param capacity 缓存最大容量*/public LRUCache(int capacity) {this.capacity = capacity;this.accessOrder = new LinkedList<>();this.cacheMap = new HashMap<>(capacity); // 初始化指定容量以提高效率}/*** 获取键对应的值,并更新访问顺序* @param key 目标键* @return 对应的值,若不存在则返回-1*/public int get(int key) {if (!cacheMap.containsKey(key)) {return -1; // 键不存在时返回-1}// 更新该键的访问顺序(移到链表头部)updateAccessOrder(key);return cacheMap.get(key);}/*** 插入或更新键值对,维护缓存容量* @param key 目标键* @param value 对应的值*/public void put(int key, int value) {if (capacity <= 0) {return; // 容量为0时不执行任何操作}if (cacheMap.containsKey(key)) {// 键已存在:更新值并调整访问顺序updateAccessOrder(key);} else {// 键不存在:检查是否需要淘汰旧数据if (accessOrder.size() >= capacity) {evictLeastRecentlyUsed(); // 淘汰最久未使用的键}// 将新键插入到访问顺序的头部accessOrder.addFirst(key);}// 更新或插入键值对(HashMap会自动处理更新逻辑)cacheMap.put(key, value);}/*** 将指定键移动到访问顺序的头部(最近访问)* @param key 目标键*/private void updateAccessOrder(int key) {accessOrder.remove((Integer) key); // 从链表中移除旧位置(需拆箱为Integer)accessOrder.addFirst(key); // 插入到头部}/*** 淘汰最久未使用的键(链表尾部元素)*/private void evictLeastRecentlyUsed() {int removedKey = accessOrder.removeLast(); // 移除链表尾部元素(最久未使用)cacheMap.remove(removedKey); // 同步从HashMap中删除}
}

3. 关键点解析

  1. LinkedList维护访问顺序,头部是最新访问的数据
  2. HashMap提供O(1)时间的键值访问
  3. 访问数据时通过updateAccess方法更新位置
  4. 容量满时从链表尾部淘汰最久未使用的数据

4. 复杂度分析

  • 时间复杂度:
    • get操作:O(1)
    • put操作:O(1)
  • 空间复杂度:O(capacity)

三、LFU缓存实现详解

1. 核心思想

LFU基于"使用频率最低"原则淘汰数据,同时考虑访问频率和访问时间。

2. 完整实现代码

import java.util.LinkedHashSet;
import java.util.HashMap;
import java.util.Map;class LFUCache {// 缓存容量(final修饰,确保不可变)private final int capacity;// 当前最小访问频率(用于快速定位需要淘汰的键)private int minFrequency;// 键到值的映射(存储实际数据)private final Map<Integer, Integer> keyToValue;// 键到访问频率的映射private final Map<Integer, Integer> keyToFrequency;// 频率到键集合的映射(使用LinkedHashSet维护相同频率下的访问顺序)private final Map<Integer, LinkedHashSet<Integer>> frequencyToKeys;/*** 构造函数,初始化缓存容量和数据结构* @param capacity 缓存最大容量*/public LFUCache(int capacity) {this.capacity = capacity;this.minFrequency = 0; // 初始最小频率为0(无数据时)this.keyToValue = new HashMap<>();this.keyToFrequency = new HashMap<>();this.frequencyToKeys = new HashMap<>();}/*** 获取键对应的值,并更新访问频率* @param key 目标键* @return 对应的值,若不存在则返回-1*/public int get(int key) {if (!keyToValue.containsKey(key)) {return -1; // 键不存在时返回-1}// 增加该键的访问频率increaseFrequency(key);return keyToValue.get(key);}/*** 插入或更新键值对,维护缓存容量和频率信息* @param key 目标键* @param value 对应的值*/public void put(int key, int value) {if (capacity <= 0) {return; // 容量为0时不执行任何操作}if (keyToValue.containsKey(key)) {// 键已存在:更新值并增加频率keyToValue.put(key, value);increaseFrequency(key);return;}// 键不存在:检查是否需要淘汰旧数据if (keyToValue.size() >= capacity) {evictLeastFrequent(); // 淘汰访问频率最低的键}// 插入新键值对(初始频率为1)keyToValue.put(key, value);keyToFrequency.put(key, 1);// 初始化频率为1的键集合(若不存在则创建)frequencyToKeys.computeIfAbsent(1, k -> new LinkedHashSet<>()).add(key);// 新插入数据后,最小频率必定为1(初始插入或淘汰后重置)this.minFrequency = 1;}/*** 增加指定键的访问频率,并更新相关数据结构* @param key 目标键*/private void increaseFrequency(int key) {int currentFrequency = keyToFrequency.get(key);// 频率加1keyToFrequency.put(key, currentFrequency + 1);// 从原频率集合中移除该键LinkedHashSet<Integer> oldFrequencySet = frequencyToKeys.get(currentFrequency);oldFrequencySet.remove(key);// 如果原频率集合为空,移除该频率条目if (oldFrequencySet.isEmpty()) {frequencyToKeys.remove(currentFrequency);// 如果移除的是当前最小频率,需要更新minFrequencyif (currentFrequency == minFrequency) {minFrequency++;}}// 将键添加到新频率的集合中(自动创建集合若不存在)frequencyToKeys.computeIfAbsent(currentFrequency + 1, k -> new LinkedHashSet<>()).add(key);}/*** 淘汰访问频率最低的键(优先淘汰频率最低且最久未使用的键)*/private void evictLeastFrequent() {// 获取最小频率对应的键集合LinkedHashSet<Integer> keysToEvict = frequencyToKeys.get(minFrequency);// 获取该集合中最早插入的键(LinkedHashSet按插入顺序存储)int keyToRemove = keysToEvict.iterator().next();// 从集合中移除该键keysToEvict.remove(keyToRemove);// 如果集合为空,移除该频率条目(无需更新minFrequency,put操作会重置)if (keysToEvict.isEmpty()) {frequencyToKeys.remove(minFrequency);}// 从核心数据结构中移除该键keyToValue.remove(keyToRemove);keyToFrequency.remove(keyToRemove);}
}

3. 关键点解析

  1. 使用三个核心数据结构:
    • keyToValue:存储键值对
    • keyToFrequency:记录访问频率
    • frequencyToKeys:维护相同频率下的访问顺序
  2. LinkedHashSet保证同频率下的时序性
  3. minFrequency变量高效定位淘汰目标
  4. 新插入数据的初始频率总是1

4. 复杂度分析

  • 时间复杂度:
    • get操作:O(1)平均
    • put操作:O(1)平均
  • 空间复杂度:O(capacity)

四、两种算法对比

特性LRULFU
淘汰原则最近最少使用使用频率最低
数据结构哈希表+双向链表三重映射结构
时间复杂度O(1)访问和插入O(1)平均时间复杂度
优势场景突发流量、时间局部性强的访问模式稳定流量、长期热点数据
实现复杂度简单较复杂

五、生产环境建议

  1. 选择依据

    • LRU适合时间局部性强的场景
    • LFU适合需要识别长期热点的场景
  2. 优化建议

    • 使用Caffeine等成熟缓存库
    • 高并发场景采用分片缓存策略
  3. 扩展思考

    • 可结合TTL过期策略
    • 考虑LRU-K等混合算法
http://www.dtcms.com/wzjs/131855.html

相关文章:

  • 网站开发 招聘 龙岩网络服务器是指什么
  • 幻日网站建设国内打开google网页的方法
  • 做视频采集网站犯法微博指数
  • 果农在哪些网站做推广百度收录网站需要多久
  • 比较酷炫的企业网站关键词优化怎么做
  • 聊城做网站推广地方百度视频下载
  • 石景山区网站建设百度竞价代运营托管
  • 那种类型的网站可以自己做也可以赚钱惠州seo排名优化
  • 网站维护内容及费用企业营销策划公司
  • 网站开发具备的相关知识网络媒体发稿平台
  • 学校网站开发的项目背景谷歌chrome官网
  • 网络公司做网站价格站外推广平台有哪些
  • 溧水做网站价格seo快速排名培训
  • 通州北苑网站建设杭州百度seo
  • 专业网站建设宣传网站有哪些
  • 大学做兼职英语作文网站谷歌平台推广外贸
  • 宝塔做网站最好的bt种子搜索引擎
  • 桂林技术交流站怎么把网站排名优化
  • 大连做网站不错的公司关键词seo是什么
  • 专门给代购做的网站网络推广平台哪家公司最好
  • 天河做网站平台湘潭网页设计
  • 商业网站制作游戏代理
  • 做采集网站赚钱百度开户资质
  • 网站开发的形式有( )如何做好网络营销
  • 深圳集团网站建设公司好宁波seo网络推广优质团队
  • 项目网站设计磁力猫搜索引擎入口官网
  • 网站专题页面文案设计自己怎么优化网站排名
  • 网站域名被注销重新备案怎么做小学生抄写新闻20字
  • 软件定制论坛网站优化方案
  • 网站平台建设经费预算为什么中国禁止谷歌浏览器