Java實現LRU緩存方法?
/**
* 可以使用雙向鏈表和哈希表實現一個LRU緩存
* 1、使用雙向鏈表實現的隊列,隊列的最大容量是緩存的大小。在使用的過程中,把最近使用的頁面移動到隊列頭,最近沒有使用的放到隊尾
* 2、使用一個哈希表,把頁號作為鍵,把緩存在隊列中的節點的的地址作為值
* 當引用一個頁面時,這個所需的頁面在內存中,需要把這個頁對應的節點移動到隊列的前面,並且更新在哈希表中結點的地址
* 當所需的頁面不在內存時,我們把它存儲到內存中
* 當隊列滿時,那么就從隊列尾部移除一個結點,並將新結點添加到隊列的前面
*/
package com.lru; import java.util.HashMap; /** * @ClassName LRU * @Description 最近最少使用 * @Author Administrator * @Date 2019/5/30 20:05 * @Version 1.0 **/ public class LRU<K,V> { /** * 可以使用雙向鏈表和哈希表實現一個LRU緩存 * 1、使用雙向鏈表實現的隊列,隊列的最大容量是緩存的大小。在使用的過程中,把最近使用的頁面移動到隊列頭,最近沒有使用的放到隊尾 * 2、使用一個哈希表,把頁號作為鍵,把緩存在隊列中的節點的的地址作為值 * 當引用一個頁面時,這個所需的頁面在內存中,需要把這個頁對應的節點移動到隊列的前面,並且更新在哈希表中結點的地址 * 當所需的頁面不在內存時,我們把它存儲到內存中 * 當隊列滿時,那么就從隊列尾部移除一個結點,並將新結點添加到隊列的前面 */ private final int MAX_CACHE_SIZE; private Entry first; private Entry last; private HashMap<K, Entry<K, V>> hashMap; /** * * @param cacheSize 初始的緩存的大小 */ public LRU(int cacheSize) { this.MAX_CACHE_SIZE = cacheSize; hashMap = new HashMap<K, Entry<K, V>>(); } public void put(K key, V value) { Entry entry = getEntry(key); if(entry == null) { if(hashMap.size() >= MAX_CACHE_SIZE) { hashMap.remove(last.key); removeLast(); } entry = new Entry(); entry.key = key; } entry.value = value; moveToFirst(entry); hashMap.put(key, entry); } /** * 獲取key鍵對應的值 * @param key * @return */ public V get(K key) { Entry<K, V> entry = getEntry(key); if(entry == null) { return null; } // 將當前entry移動到開頭 moveToFirst(entry); return entry.value; } /** * 將最近訪問的entry移動到開頭 * @param entry */ private void moveToFirst(Entry entry) { /** * 1、如果是第一個元素,則不需要移動 */ if(entry == first) { return; } /** * 2、如果entry節點的前面的節點存在,則改變前面的節點的指向 */ if(entry.pre != null) { entry.pre.next = entry.next; } /** * 3、如果entry節點的后面存在,則改變后面節點的前向指向 */ if(entry.next != null) { entry.next.pre = entry.pre; } /** * 4、如果當前結點是最后一個結點,那么該變last指向 */ if(entry == last) { last = last.pre; } /** * 5、 */ if(first == null || last == null) { first = last = entry; return ; } /** * 移動entry到隊頭 */ entry.next = first; first.pre = entry; entry.pre = null; } /** * 刪除 */ private void removeLast() { if(last != null) { last = last.pre; if(last == null) { first = null; } else { last.next = null; } } } private Entry<K, V> getEntry(K key) { return hashMap.get(key); } /** * 存儲鍵值的節點 * @param <K> * @param <V> */ class Entry<K, V> { public Entry pre; public Entry next; public K key; public V value; } }
測試主類
package com.lru; /** * @ClassName Main * @Description LRU緩存測試主類 * @Author Administrator * @Date 2019/5/30 20:29 * @Version 1.0 **/ public class Main { public static void main(String[] args) { LRU<Integer, String> lru = new LRU<>(5); lru.put(1, "String1"); lru.put(2, "String2"); lru.put(3, "String3"); lru.put(4, "String4"); lru.put(5, "String5"); lru.put(6, "String6"); System.out.println(lru.get(1)); } }