日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LinkedHashMap实现LRU缓存算法

發布時間:2024/1/17 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LinkedHashMap实现LRU缓存算法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

緩存這個東西就是為了提高運行速度的,由于緩存是在寸土寸金的內存里面,不是在硬盤里面,所以容量是很有限的。

LRU這個算法就是把最近一次使用時間離現在時間最遠的數據刪除掉。

先說說List:每次訪問一個元素后把這個元素放在 List一端,這樣一來最遠使用的元素自然就被放到List的另一端。緩存滿了t的時候就把那最遠使用的元素remove掉。但更實用的是 HashMap。因為List太慢,要刪掉的數據總是位于List底層數組的第一個位置,刪掉之后,后面的數據要向前補位。。所以復雜度是O(n),那就用鏈表結構的LinkedHashMap唄~,LinkedHashMap默認的元素順序是put的順序,但是如果使用帶參數的構造函數,那么 LinkedHashMap會根據訪問順序來調整內部 順序。

LinkedHashMap的get()方法除了返回元素之外還可以把被訪問的元素放到鏈表的底端,這樣一來每次頂端的元素就是remove的元素。

構造函數如下:

public LinkedHashMap (int initialCapacity, float loadFactor, boolean accessOrder);
  • 1
  • 2

initialCapacity 初始容量

loadFactor 加載因子,一般是 0.75f

accessOrder false 基于插入順序 true 基于訪問順序(get一個元素后,這個元素被加到最后,使用了LRU 最近最少被使用的調度算法)

看一下LinkedHashMap的相關實現源碼吧:

// 雙向鏈表的 head節點 private transient Entry<K,V> header;// 訪問順序 true:訪問順序;false:插入順序 private final boolean accessOrder;// get方法 每個get之后,都要進行recordAccess操作 public V get(Object key) {Entry<K,V> e = (Entry<K,V>)getEntry(key);if (e == null)return null;e.recordAccess(this);return e.value; }// recordAccess 方法中,先remove該節點,再在head之間添加節點,表示最近訪問了 void recordAccess(HashMap<K,V> m) {LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;if (lm.accessOrder) {lm.modCount++;remove();addBefore(lm.header);} }// 刪除該節點 private void remove() {before.after = after;after.before = before; }private void addBefore(Entry<K,V> existingEntry) {after = existingEntry;before = existingEntry.before;before.after = this;after.before = this; }// 添加新的entry時,如果需要刪除eldest節點,就會刪除head.after,如果是訪問順序,也就是最早以前訪問的節點 void addEntry(int hash, K key, V value, int bucketIndex) {super.addEntry(hash, key, value, bucketIndex);// Remove eldest entry if instructedEntry<K,V> eldest = header.after;if (removeEldestEntry(eldest)) {removeEntryForKey(eldest.key);} } // 默認的removeEldestEntry方法是返回false的,也就是不會進行刪除,而是進行擴容protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {return false; } 這是實現LRU的關鍵,我們可以重寫這個方法,讓其刪除eldest entry;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

來個例子吧:?
import java.util.*;

class Test { public static void main(String[] args) throws Exception{ Map<Integer,Integer> map=new LinkedHashMap<>(10,0.75f,true); map.put(9,3); map.put(7,4); map.put(5,9); map.put(3,4); //現在遍歷的話順序肯定是9,7,5,3 //下面訪問了一下9,3這個鍵值對,輸出順序就變嘍~ map.get(9); for(Iterator<Map.Entry<Integer,Integer>> it=map.entrySet().iterator();it.hasNext();){ System.out.println(it.next().getKey()); } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

輸出?
7?
5?
3?
9

好玩吧~?
下面開始實現LRU緩存嘍~

import java.util.*; //擴展一下LinkedHashMap這個類,讓他實現LRU算法 class LRULinkedHashMap<K,V> extends LinkedHashMap<K,V>{ //定義緩存的容量 private int capacity; private static final long serialVersionUID = 1L; //帶參數的構造器 LRULinkedHashMap(int capacity){ //調用LinkedHashMap的構造器,傳入以下參數 super(16,0.75f,true); //傳入指定的緩存最大容量 this.capacity=capacity; } //實現LRU的關鍵方法,如果map里面的元素個數大于了緩存最大容量,則刪除鏈表的頂端元素 @Override public boolean removeEldestEntry(Map.Entry<K, V> eldest){ System.out.println(eldest.getKey() + "=" + eldest.getValue()); return size()>capacity; } } //測試類 class Test{ public static void main(String[] args) throws Exception{ //指定緩存最大容量為4 Map<Integer,Integer> map=new LRULinkedHashMap<>(4); map.put(9,3); map.put(7,4); map.put(5,9); map.put(3,4); map.put(6,6); //總共put了5個元素,超過了指定的緩存最大容量 //遍歷結果 for(Iterator<Map.Entry<Integer,Integer>> it=map.entrySet().iterator();it.hasNext();){ System.out.println(it.next().getKey()); } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

輸出結果如下?
9=3?
9=3?
9=3?
9=3?
9=3?
7?
5?
3

分析一下:使用帶參數構造器,且啟用LRU模式的LinkedHashMap會在每次有新元素加入的時候,判斷當前儲存元素是否超過了緩存上限,也就是執行?
一次removeEldestEntry方法,看最后的遍歷結果,發現果然把9刪除了,LRU發揮作用了~

總結

以上是生活随笔為你收集整理的LinkedHashMap实现LRU缓存算法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。