如何實現 LRU 緩存:基于LinkedHashMap?

全文目錄:

    • 開篇語
    • 前言
    • 1. LinkedHashMap 簡介
      • 1.1 LinkedHashMap 的構造方法
    • 2. 基于 LinkedHashMap 實現 LRU 緩存
      • 2.1 設計思路
      • 2.2 實現步驟
      • 2.3 代碼說明
      • 2.4 測試案例
      • 2.5 解釋
    • 3. LRU 緩存優化
      • 3.1 `removeEldestEntry()` 方法的靈活性
      • 3.2 內存管理
    • 4. 總結
    • 文末

開篇語

哈嘍,各位小伙伴們,你們好呀,我是喵手。運營社區:C站/掘金/騰訊云/阿里云/華為云/51CTO;歡迎大家常來逛逛

??今天我要給大家分享一些自己日常學習到的一些知識點,并以文字的形式跟大家一起交流,互相學習,一個人雖可以走的更快,但一群人可以走的更遠。

??我是一名后端開發愛好者,工作日常接觸到最多的就是Java語言啦,所以我都盡量抽業余時間把自己所學到所會的,通過文章的形式進行輸出,希望以這種方式幫助到更多的初學者或者想入門的小伙伴們,同時也能對自己的技術進行沉淀,加以復盤,查缺補漏。

小伙伴們在批閱的過程中,如果覺得文章不錯,歡迎點贊、收藏、關注哦。三連即是對作者我寫作道路上最好的鼓勵與支持!

前言

在很多實際的應用中,尤其是需要緩存數據的場景下,我們經常會遇到 LRU(Least Recently Used,最近最少使用)緩存。LRU 緩存是通過淘汰最久未使用的緩存數據來節省內存空間。對于高效的 LRU 緩存,我們不僅要保證快速的查找、插入和刪除操作,還要能夠快速地淘汰最久未使用的元素。

在 Java 中,基于 LinkedHashMap 實現 LRU 緩存是非常簡便和高效的,因為 LinkedHashMap 本身提供了按照訪問順序迭代的能力,我們可以利用這一特性輕松實現 LRU 緩存。


1. LinkedHashMap 簡介

LinkedHashMapHashMap 的一個子類,它基于哈希表實現,并且維護了插入順序或訪問順序。這使得 LinkedHashMap 特別適合于實現緩存,尤其是在需要按訪問順序迭代時。

1.1 LinkedHashMap 的構造方法

  • LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder):
    • initialCapacity:初始容量。
    • loadFactor:負載因子。
    • accessOrder:如果設置為 true,則按照訪問順序排序;如果設置為 false,則按照插入順序排序。

accessOrder 設置為 true 時,LinkedHashMap 會在每次訪問(get 或 put 操作)時,將訪問的元素移動到鏈表的末尾。這個特性讓我們能夠輕松地實現 LRU 緩存。


2. 基于 LinkedHashMap 實現 LRU 緩存

2.1 設計思路

  1. 緩存大小限制:我們需要為緩存設定一個最大容量 capacity,當緩存容量超過該值時,我們就需要淘汰最久未使用的元素。
  2. LRU 淘汰規則:在每次插入或訪問元素時,我們將該元素移動到鏈表的末尾,這樣鏈表的頭部始終保存著最久未使用的元素。當緩存容量超過限制時,我們可以直接刪除鏈表頭部的元素。
  3. 使用 LinkedHashMap:利用 LinkedHashMapaccessOrder 的特性,結合 removeEldestEntry() 方法來自動刪除最久未使用的元素。

2.2 實現步驟

我們可以創建一個繼承自 LinkedHashMap 的類,并重寫 removeEldestEntry() 方法,該方法會在每次插入新元素時被調用。

import java.util.LinkedHashMap;
import java.util.Map;public class LRUCache<K, V> extends LinkedHashMap<K, V> {private final int capacity;// 構造函數,初始化容量和 accessOrderpublic LRUCache(int capacity) {super(capacity, 0.75f, true);  // 第三個參數 true 表示按訪問順序排序this.capacity = capacity;}// 重寫 removeEldestEntry 方法,當緩存容量超出時,移除最久未使用的條目@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {return size() > capacity;}// 獲取緩存中的值public V get(K key) {return super.getOrDefault(key, null);}// 插入緩存值public void put(K key, V value) {super.put(key, value);}
}

2.3 代碼說明

  • LRUCache 類繼承自 LinkedHashMap,并通過構造函數設置了 accessOrdertrue,這使得每次訪問元素時,該元素都會被移到鏈表的末尾。
  • removeEldestEntry() 方法會在每次插入新元素時檢查緩存的大小。如果緩存的大小超過了設定的容量,它會返回 true,從而自動移除最久未使用的元素。
  • get(K key)put(K key, V value) 方法分別用于獲取和插入緩存中的數據。

2.4 測試案例

public class Main {public static void main(String[] args) {// 創建一個容量為 3 的 LRU 緩存LRUCache<Integer, String> cache = new LRUCache<>(3);// 向緩存中插入數據cache.put(1, "A");cache.put(2, "B");cache.put(3, "C");// 打印緩存內容System.out.println(cache); // 輸出: {1=A, 2=B, 3=C}// 訪問元素 1cache.get(1); // 使元素 1 最近訪問// 插入新的元素,此時緩存超過容量,元素 2 將被移除cache.put(4, "D");// 打印緩存內容System.out.println(cache); // 輸出: {3=C, 1=A, 4=D}}
}

輸出:

{1=A, 2=B, 3=C}
{3=C, 1=A, 4=D}

2.5 解釋

  1. 初始時,緩存的容量為 3,元素 {1=A, 2=B, 3=C} 被插入緩存。
  2. 當訪問 get(1) 時,元素 1 被移動到鏈表的末尾。
  3. 當插入元素 4=D 時,由于緩存已經滿了,元素 2(最久未訪問)被自動刪除,最終緩存內容為 {3=C, 1=A, 4=D}

3. LRU 緩存優化

3.1 removeEldestEntry() 方法的靈活性

通過 removeEldestEntry() 方法,我們可以根據不同的需求定制緩存的淘汰規則。例如,我們可以根據某些條件(如元素的大小、元素的過期時間等)來決定是否刪除最久未使用的元素。

3.2 內存管理

雖然 LinkedHashMapaccessOrder 特性和 removeEldestEntry() 方法讓我們能夠很方便地實現 LRU 緩存,但也需要注意緩存大小和內存使用的平衡。特別是當緩存需要存儲大量數據時,合理設置緩存容量和定期清理緩存非常重要。


4. 總結

  • 使用 LinkedHashMap 實現 LRU 緩存的方式簡潔高效,特別適合需要按訪問順序管理緩存數據的場景。
  • 通過重寫 removeEldestEntry() 方法,我們能夠在緩存超出容量時自動移除最久未使用的元素。
  • 這種方法不僅具有較高的性能,還能避免重復的復雜操作,方便開發者實現高效的緩存管理。

LRU 緩存的實現,幫助我們在高效處理數據時保持內存的合理使用,避免內存溢出或緩存過期問題的出現。

… …

文末

好啦,以上就是我這期的全部內容,如果有任何疑問,歡迎下方留言哦,咱們下期見。

… …

學習不分先后,知識不分多少;事無巨細,當以虛心求教;三人行,必有我師焉!!!

wished for you successed !!!


??若喜歡我,就請關注我叭。

??若對您有用,就請點贊叭。
??若有疑問,就請評論留言告訴我叭。


版權聲明:本文由作者原創,轉載請注明出處,謝謝支持!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82747.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82747.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82747.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring Boot測試框架全面解析

Spring Boot測試框架基礎 Spring Boot通過增強Spring測試框架的能力,為開發者提供了一系列簡化測試流程的新注解和特性。該框架建立在成熟的Spring測試基礎之上,通過自動化配置和專用注解顯著提升了測試效率。 核心依賴配置 要使用Spring Boot的全部測試功能,只需在項目中…

Spring Boot 整合 Spring Data JPA、strategy 的策略區別、什么是 Spring Data JPA

DAY29.2 Java核心基礎 Spring Boot 整合 Spring Data JPA Spring Data JPA根據具體的數據庫分為不同的子模塊&#xff0c;無論是關系型數據庫和非關系型數據庫&#xff0c;Spring Data都提供了支持 Mysql&#xff1a;Spring Data JPA Redis&#xff1a;Spring Data Redis …

Ubuntu 服務器配置與 Cloudflare Tunnel 部署指南 免費內網穿透家用服務器

Ubuntu 服務器配置與 Cloudflare Tunnel 部署指南 本文檔總結了服務器配置相關內容&#xff0c;包括 Ubuntu 服務器配置、硬盤擴容、靜態 IP 設置以及 Cloudflare Tunnel 的部署步驟。 目錄 硬盤分區與擴容設置靜態 IPCloudflare Tunnel 部署SSH 通過 Cloudflare Tunnel常見…

降低實驗檢測報告編制耗時 質檢LIMS系統的應用策略

在質檢工作流程中&#xff0c;檢測報告編制往往是耗時耗力的關鍵環節。傳統人工編制報告不僅效率低下&#xff0c;還容易出現數據錯誤、格式不統一等問題。質檢 LIMS 系統憑借其強大的自動化、智能化功能&#xff0c;為檢測報告編制帶來革命性變革&#xff0c;能夠將編制時間減…

同為.net/C#的跨平臺運行時的mono和.net Core有什么區別?

Mono 和 .NET Core&#xff08;現已統一為 .NET&#xff09;都是 .NET 生態的跨平臺實現&#xff0c;但它們在設計目標、技術特性和應用場景上有顯著區別。以下是詳細對比&#xff1a; ??1. 歷史背景?? ??項目????誕生時間????開發者????當前狀態????Mo…

Android AIDL Hal最低保證出現的問題

1. AIDL HAL 的“最低保證”特性 &#xff08;1&#xff09;協議層級的強制支持 在 IComposer AIDL 接口定義中&#xff08;如 android.hardware.graphics.composer3&#xff09;&#xff0c;Google 已經將部分功能列為 必須支持的特性&#xff08;MUST&#xff09;。例如&am…

蘋果FINDMY和谷歌FIND HUB增強共享位置功能

近期&#xff0c;蘋果Findmy增強了追蹤和分享丟失物品位置方面的功能&#xff0c;“共享物品位置”&#xff0c;用戶可以安全地與航空a公司等第三方分享丟失物品的位置&#xff0c;以便于行李找回。 iOS 18.2的這一新功能使用戶可以輕松、安全地與航空公司等第三方分享AirTag或…

基于GA遺傳優化的FIR濾波器幅頻相頻均衡補償算法matlab仿真

目錄 1.程序功能描述 2.測試軟件版本以及運行結果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 在數字信號處理領域&#xff0c;有限沖激響應&#xff08;FIR&#xff09;濾波器因其結構簡單、穩定性好且易于實現線性相位等優點被廣泛應用。然而&#xff0c;實…

雙路物理CPU機器上安裝Ubuntu并部署KVM以實現系統多開

在雙路物理CPU機器上安裝Ubuntu并部署KVM以實現系統多開&#xff0c;并追求性能最優&#xff0c;需要從硬件、宿主機系統、KVM配置、虛擬機配置等多個層面進行優化。 以下是詳細的操作指南和優化建議&#xff1a; 階段一&#xff1a;BIOS/UEFI 設置優化 (重啟進入) 啟用虛擬化…

adb查看、設置cpu相關信息

查內存 adb shell dumpsys meminfo查CPU top -m 10打開 system_monitor adb shell am start -n eu.chainfire.perfmon/.LaunchActivity設置CPU的核心數 在/sys/devices/system/cpu目錄下可以看到你的CPU有幾個核心&#xff0c;如果是雙核&#xff0c;就是cpu0和cpu1&#xff0c…

【Unity基礎】Unity新手實戰教程:用ScriptableObject控制Cube顏色

目錄 項目概述&#x1f6e0;? 完整操作步驟&#xff08;10分鐘內完成&#xff09;步驟1&#xff1a;創建ScriptableObject類步驟2&#xff1a;創建顏色配置資產步驟3&#xff1a;創建Cube控制器步驟4&#xff1a;設置場景和Cube步驟5&#xff1a;添加簡單UI提示步驟6&#xff…

One Year~

入局 作為科班學生&#xff0c;沒事就在CSDN閑逛&#xff0c;只作為旁觀者的身份去體會別人的好文。當時也沒想著說去自己寫一些博客記錄學習過程。相信大多數同學和我有一樣的心理。 但在看魚皮哥的課程時&#xff0c;發現他有著寫文檔和博客的習慣&#xff0c;整理自己的思路…

【Redis】第3節|深入理解Redis線程模型

一、Redis基礎認知 &#xff08;一&#xff09;定義與定位 Redis&#xff08;Remote Dictionary Server&#xff09;是開源高性能鍵值數據庫&#xff0c;核心特點如下&#xff1a; 數據結構豐富&#xff1a;支持字符串、哈希、列表、集合、有序集合等復雜數據類型&#xff0…

vben-admin 2.8.0 版本修改 axios響應處理邏輯

此前端框架下的 Axios 在后端返回的結果老是無法正常解析&#xff0c;找到他源碼的封裝類&#xff0c;修正這個問題 文件位于 src\utils\http\axios\index.ts 修改前 transformResponseHook: (res: AxiosResponse<Result>, options: RequestOptions) > {const { t }…

深入理解JavaScript設計模式之原型模式

目錄 前言引入原型模式頭腦風暴傳統方式 vs 原型模式實戰案例&#xff1a;飛機大戰中的分身術 原型模式實現的關鍵秘密實戰演練&#xff1a;造一架能分身的飛機克隆是創建對象的手段原型模式&#xff1a;輕裝上陣的造物術 原型編程范型的一些規則原型編程的四大門規&#xff1a…

【數據庫】概述(純理論)

數據庫系統引論 數據管理系統的發展 數據管理&#xff1a;對數據分類、組織、編碼、存儲、檢索、維護 發展&#xff1a;人工管理、文件系統、數據庫系統 40-50年代 人工管理 數據不保存&#xff0c;沒有專門軟件管理數據&#xff0c;應用程序完全依賴于數據&#xff0c;數據…

語音合成之十七 語音合成(TTS)中文自然度:問題、成因、解決方案

語音合成&#xff08;TTS&#xff09;中文自然度&#xff1a;問題、成因、解決方案 中文TTS系統基本架構中文TTS常見問題深度剖析與解決方案音色跳變成因分析解決方案 聲調與重讀錯誤成因分析業界解決方案 漏讀與斷句錯誤成因分析業界解決方案 在跨語言TTS系統比較中&#xff0…

我在 Linux 進程管理中踩過的坑:僵尸、瞬時與不可中斷進程實戰實錄

作為運維老鳥&#xff0c;我曾在 Linux 進程管理上栽過不少跟頭。記得第一次遇到滿屏僵尸進程時&#xff0c;服務器直接卡到連 SSH 都登不上&#xff0c;看著ps命令里一排排刺眼的Z狀態進程&#xff0c;手心直冒冷汗。后來又碰到過瞬時進程搞崩日志系統&#xff0c;明明監控顯示…

【設計模式】簡單工廠模式,工廠模式,抽象工廠模式,單例,代理,go案例區分總結

工廠模式三種類型&#xff1a; 一、簡單工廠模式&#xff08;Simple Factory&#xff09; 定義&#xff1a; 用一個工廠類&#xff0c;根據傳入的參數決定創建哪一種具體產品類實例。 面試說法&#xff1a; 由一個統一的工廠創建所有對象&#xff0c;增加新產品時需要修改工…

某標桿房企BI平臺2.0升級實踐

當房地產行業從“規模競賽”轉向“精益運營”&#xff0c;數字化轉型成為破局關鍵。某千億房企攜手億信華辰&#xff0c;以“用數據重構業務價值鏈”為目標&#xff0c;歷經6個月完成BI平臺戰略性升級。在這場從“數據可視化”到“決策智能化”的躍遷中&#xff0c;億信華辰ABI…