前面注释掉的部分是简单的用LinkedHashMap写的LRU,属于没有技术含量,也不能很好的理解LRU.
import java.util.HashMap;
/**
* @ClassName LRU 借助LinkedHashMap,重写removeEldestEntry,调用LinkedHashMap的size()方法来判断存入的元素个数。
* @Description TODO
* @Author Handoking
* @Date 2019/7/17 8:54
**/
//public class LRU<K,V> extends LinkedHashMap<K,V> {
// int size =5;
// public LRU(int size){
// super(16,0.75f,true);
// this.size = size;
// }
//
// @Override
// protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
// return size()>size;
// }
//}
/**
* @ClassName LRU 使用map和双链表实现。
* @Description TODO
* @Author Handoking
* @Date 2019/7/17 8:54
**/
public class LRU<K,V>{
class CacheNode {
CacheNode pre;
CacheNode next;
Object key;
Object value;
CacheNode(Object key, Object value) {
this.key = key;
this.value = value;
this.pre = null;
this.next =null;
}
CacheNode(){
}
}
private int cacheSize;
private HashMap<K,CacheNode> cache;
private CacheNode head;
private CacheNode tail;
public LRU(int size){
this.cacheSize = size;
cache = new HashMap<>();
}
public Object put(K k,V v){
CacheNode node = cache.get(k);
Object temp=-11111;
if(node==null){
//当前节点不存在,判断缓存是否已经存满,若存满,那么删除尾节点,同时删除map中存储的数据。
if(cache.size()>=cacheSize){
cache.remove(tail.key);
delectTail();
}
//创建新结点
node =new CacheNode();
node.key = k;
}else{
temp = node.value;
}
//无论存在不存在,都需要将此节点移动到链表头,因此统一合并操作。
node.value = v;
cache.put(k,node);
moveToHead(node);
//返回旧值
if(!temp.equals(-11111)){
return temp;
}
return -1;
}
public Object get(K k){
//get的操作需要判断,如果结点存在那么返回值并将此节点移动到链表头部
//如果不存在,返回空值
CacheNode node = cache.get(k);
if(node==null){
return null;
}
moveToHead(node);
return node.value;
}
private void delectTail(){
if(tail!=null){
tail = tail.pre;
if (tail==null){
//此时tail为空值时,说明头节点和尾节点为同一节点,删除后整个链表为空
head=null;
}else{
tail.next =null;
}
}
}
private void moveToHead(CacheNode node){
//如果是头节点,那么不需要操作
if(node==head){
return;
}
//如果不是头节点,
if (node==tail){
tail = tail.pre;
tail.next=null;
}
if(node.next!=null){
node.next.pre = node.pre;
}
if(node.pre!=null){
node.pre.next = node.next;
}
//至关重要,如果是首次插入,那么head为空
if(head==null||tail==null){
head=tail =node;
return;
}
node.next = head;
head.pre = node;
head =node;
head.pre = null;
}
public Object remove(K k){
//如果值存在,链表中调整前后的指针删除节点,cache中使用map直接删除
CacheNode node = cache.get(k);
if (node!=null){
if(node==head){
head =node.next;
head.pre =null;
}
if(node ==tail){
tail = node.pre;
tail.next=null;
}
if(node.pre!=null){
node.pre.next = node.next;
}
if (node.next!=null) {
node.next.pre = node.pre;
}
}
//hashMap的remove方法会值在不存在时,返回空值,存在时返回被删除的值,因此可以合并到这里一并删除缓存里的值
return cache.remove(k);
}
public void clear(){
//链表清空,map清空
head =null;
tail =null;
cache.clear();
}
//测试
public static void main(String[] args) {
LRU<Integer,String> lru = new LRU<>(3);
lru.put(1, "a");
lru.put(2, "b");
lru.put(3, "c");
lru.get(1);
lru.put(4, "d");
System.out.println( lru.put(1, "aa"));
lru.put(2, "bb");
lru.put(5, "e");
lru.get(1);
System.out.println(lru.remove(11));
lru.remove(1);
lru.put(1, "aaa");
}
}