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));
}
}
