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

建设一个网站花多少钱中企动力网站怎么样

建设一个网站花多少钱,中企动力网站怎么样,装修公司网站怎么做的,html5公司网站源码深入理解缓存淘汰算法: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/573570.html

相关文章:

  • 网站外包公司该如何运营诸城 建设外贸网站
  • 淘宝联盟网站怎么做wordpress .htaccess
  • wordpress英文站更新通知目录深圳自建站有哪些大公司
  • 网站定位包括哪些内容杭州网站建设方案书
  • 南方医科大学精品课程建设网站网页代码是什么语言
  • 兰州网站设计厂家wordpress网页编辑
  • 苏州市相城区建设局网站企业网络推广公司
  • 找外贸客户的网站中国电力建设公司官网
  • 自己搞个网站做网页一个页面多少钱
  • 免费推广网站排名摄图网官网
  • 宁波网站优化方案留言板网站怎么做
  • 企业网站模板源码有哪些简述网站开发过程
  • 怎么样做网站才能适应手机屏幕店面建设网站的必要性
  • 玮科网站建设凡科网手机版下载
  • 江西省城乡和住房建设部网站优质手机网站建设企业
  • 网站内容与模板设计方案如何建设自己的淘宝客网站
  • 济南商城网站建设公司全国旅游服务平台
  • 黄金网站大全免费2023中华室内设计师
  • 公司网站开发费用济南兴田德润o评价项目网手游
  • 荆州网站建设荆州怀化火车站网站
  • 福州百度网站快速优化淄博平台公司
  • 便宜建站空间机关网站建设情况汇报
  • 安徽东皖建设集团有限公司网站电子公章印章在线制作网站
  • 做eso哪家网站好手机网站安全证书过期怎么处理
  • 山东建设厅网站网络营销推广岗位
  • 中砼建设有限公司网站重庆建设工程信息网官网安全监督
  • 自己做的网站百度搜不到昆明市住房和城乡建设局门户网站
  • 网站建设公司dyfwzxwordpress简书主题
  • 巴城镇建设网站优化网站最好的刷排名软件
  • 网站建设开发电销话术网站建设怎么选择MySQL数据库大小