更多文章,歡迎關注微信公眾號:深夜程猿
在上一篇文章簡單聊聊了LRU演算法理論篇,這裡就和大家使用單連結串列實現一個簡單的LRU演算法。其它型別的實現一樣的思路,只不過是處理的複雜程度不一樣而已。
Node.java:儲存資料的結點
package lru;
/**
* @author wu
* @since 2019/4/2
*/
public class Node<K, V> {
private V data;
private K key;
/**
* 指標,指向下一節點
*/
private Node<K, V> next;
public V getData() {
return data;
}
public void setData(V data) {
this.data = data;
}
public Node<K, V> getNext() {
return next;
}
public void setNext(Node<K, V> next) {
this.next = next;
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
}
複製程式碼
LinkedLru.java:LRU實現
package lru;
/**
* @author wu
* @since 2019/4/2
*/
public class LinkedLru<K, V> {
private Node<K, V> root;
private int maxCapacity;
private int defaultCapacity = 10;
public LinkedLru(int maxCapacity) {
if (maxCapacity <= 0) {
throw new IllegalArgumentException("maxCapacity should not less than 0");
}
this.maxCapacity = maxCapacity;
}
public int getMaxCapacity() {
return maxCapacity;
}
public LinkedLru() {
this.maxCapacity = defaultCapacity;
}
public Node<K, V> get(K key) {
if (key == null) {
throw new IllegalArgumentException("key should not be null");
}
if (root == null) {
return null;
}
Node<K, V> temp = root;
while (temp != null) {
if (key.equals(temp.getKey())) {
Node<K, V> node = new Node<>();
node.setData(temp.getData());
node.setKey(temp.getKey());
return node;
}
temp = temp.getNext();
}
return null;
}
public boolean add(Node<K, V> data) {
if (data == null) {
throw new IllegalArgumentException("can not cache null");
}
if (root == null) {
root = data;
return true;
} else {
Node<K, V> prev = root;
Node<K, V> next = root.getNext();
Node<K, V> header = root;
Node<K, V> cursor;
int index = 1;
while (true) {
index++;
cursor = prev;
if (index >= getMaxCapacity()) {
// 設定data為頭部結點
data.setNext(header);
root = data;
// 快取達到最大值,淘汰資料,此時prev就是尾部結點
cursor.setNext(null);
break;
}
if (next == null) {
// 容量沒有達到最大,已到快取尾部,並且資料還沒有快取過
data.setNext(header);
root = data;
cursor.setNext(null);
break;
}
if (next.getKey() == data.getKey()) {
// 資料存在,交換指標,資料放在首部
data.setNext(header);
prev.setNext(next.getNext());
root = data;
break;
}
prev = next;
next = next.getNext();
}
}
return true;
}
public Node<K, V> getRoot() {
return root;
}
}
複製程式碼
測試類:
package lru;
import com.alibaba.fastjson.JSON;
/**
* @author wu
* @since 2019/4/3
*/
public class Test {
public static void main(String[] args) {
LinkedLru<String, String> cache = new LinkedLru<>(10);
int pos = 0;
while (pos < 100) {
pos++;
Node<String, String> node = new Node();
node.setKey("key:" + pos);
node.setData("data:" + pos);
cache.add(node);
}
System.out.println(JSON.toJSONString(cache.getRoot()));
System.out.println(JSON.toJSONString(cache.get("key:10")));
System.out.println(JSON.toJSONString(cache.get("key:100")));
}
}
複製程式碼
輸出:
{"data":"data:100","key":"key:100","next":{"data":"data:99","key":"key:99","next":{"data":"data:98","key":"key:98","next":{"data":"data:97","key":"key:97","next":{"data":"data:96","key":"key:96","next":{"data":"data:95","key":"key:95","next":{"data":"data:94","key":"key:94","next":{"data":"data:93","key":"key:93","next":{"data":"data:92","key":"key:92","next":{"data":"data:91","key":"key:91"}}}}}}}}}}
null
{"data":"data:100","key":"key:100"}
複製程式碼