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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

LinkedHashMap 的理解以及借助其实现LRU

發布時間:2024/9/30 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LinkedHashMap 的理解以及借助其实现LRU 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LinkedHashMap 的理解以及借助其實現LRU

LinkedHashMap中有一個參數 accessOrder,這個參數定義了LinkedHashMap的訪問順序。

LinkedHashMap中繼承了Node,給Node新增了2個新的屬性before和after

static class Entry<K,V> extends HashMap.Node<K,V> {Entry<K,V> before, after;Entry(int hash, K key, V value, Node<K,V> next) {super(hash, key, value, next);} }

put方法

put方法LinkedHashMap沒有重寫,使用的是HashMap的put,但是其中還是有不同,重寫了其中幾個方法,先看代碼:

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab; Node<K,V> p; int n, i;if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;if ((p = tab[i = (n - 1) & hash]) == null)//重寫newNode方法tab[i] = newNode(hash, key, value, null);else {Node<K,V> e; K k;if (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {//重寫newNode方法p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;//重寫afterNodeAccessafterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();//重寫afterNodeInsertionafterNodeInsertion(evict);return null; }

看下重寫的這幾個方法:

newNode方法:

實現了每調用一次newNode方法,利用before和after節點可把新節點插入到隊尾。保證了一種調用newNode的順序。

Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {LinkedHashMap.Entry<K,V> p =new LinkedHashMap.Entry<K,V>(hash, key, value, e);linkNodeLast(p);return p; }private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {LinkedHashMap.Entry<K,V> last = tail;tail = p;if (last == null)head = p;else {p.before = last;last.after = p;} }

afterNodeAccess方法:

在put一個已存在的key時且 accessOrder 為true 時會調用,此方法會這個節點放到隊伍的最后。

void afterNodeAccess(Node<K,V> e) { // move node to lastLinkedHashMap.Entry<K,V> last;if (accessOrder && (last = tail) != e) {LinkedHashMap.Entry<K,V> p =(LinkedHashMap.Entry<K,V>)e, b = p.before, a = p.after;p.after = null;if (b == null)head = a;elseb.after = a;if (a != null)a.before = b;elselast = b;if (last == null)head = p;else {p.before = last;last.after = p;}tail = p;++modCount;} }

afterNodeInsertion方法

有新的Node時會調用,默認removeEldestEntry返回false,所以這一個方法什么都不做。不過可以看下如果返回不是false,則會刪除head節點。這也是實現LRU的一個基礎。

void afterNodeInsertion(boolean evict) { // possibly remove eldestLinkedHashMap.Entry<K,V> first;if (evict && (first = head) != null && removeEldestEntry(first)) {K key = first.key;removeNode(hash(key), key, null, false, true);} }protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {return false; }

get方法

get方法 會在accessOrder為true時把這個節點放到以before ,after為基礎的一個雙向鏈表的隊尾。

public V get(Object key) {Node<K,V> e;if ((e = getNode(hash(key), key)) == null)return null;if (accessOrder)afterNodeAccess(e);return e.value; }

foreach,keySet,entrySet遍歷方法

所有的遍歷在LinkedHashMap里都會重寫,都是按照以before ,after為基礎的一個雙向鏈表的順序進行遍歷。

accessOrder變量

從上面的get和put過程可以發現,access為false時,則雙向鏈表會變成一個按照插入順序的鏈表。如果為true,則會變成按照訪問順序的一個鏈表。

如何借助LinkedHashMap來實現LRU

上面看到有一個方法removeEldestEntry,默認返回false,這個方法,顧名思義就是刪除雙向鏈表最開頭的頭部節點。

所以要實現LRU,只需要這樣即可:

傳入accessOrder為true,重寫removeEldestEntry,根據緩存目標設置的size來決定在達到多少時來進行remove。

class LRU<K,V> extends LinkedHashMap<K, V>{public LRU(int initialCapacity,float loadFactor,boolean accessOrder) {super(initialCapacity,loadFactor,accessOrder);}@Overrideprotected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {if (this.size()>4) {return true;}return super.removeEldestEntry(eldest);}} 與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

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

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