题目:手写实现一个LRU缓存,支持get() put()
思路
1.可以使用最基础的单向链表处理
2.使用双向链表,可以加入hash表做优化
3.最简单的实现是使用JDK中自带的LinkedHashMap,需要重写removeEldestEntry()方法,这是LinkedHashMap提供的一个删除最老条目的方法;
Map<String,String> map = new LinkedHashMap<>(size, 0.75F,true) //false:基于插入排序,true:基于访问排序
1.基于双向链表的实现:
class LRUNode{
private String key;
private String value;
private LRUNode pre;
private LRUNode next;
public LRUNode(String key, String value) {
this.key = key;
this.value = value;
}
}
private volatile LRUNode head;
private volatile Integer lenght = 0;
public LRUcache(Integer lenght){
this.lenght = lenght;
}
public boolean put(String key,String value){
LRUNode cur = this.head;
Integer curLenght = 1;
while (null != cur && cur.next != null){
curLenght++;
if(cur.key.equals(key)){
//包含 修改其前后node的指向
cur.pre.next = cur.next;
cur.next.pre = cur.pre;
cur.pre = null;
cur.next = head;
head.pre = cur;
return true;
}else {
cur = cur.next;
}
}
//没有找到
LRUNode newNode = new LRUNode(key,value);
if(curLenght >= lenght){
//删除最后一个对象
cur.pre.next = null;
cur.pre = null;
newNode.next = head;
head.pre = newNode;
}else{
if(head != null){
head.pre = newNode;
newNode.next = head;
}
}
head = newNode;
return true;
}
public LRUNode get(String key){
if(key.isEmpty()){
throw new RuntimeException("key not is find");
}
LRUNode cur = head;
while (lenght != 0 && cur != null){
if(cur.key.equals(key)){
if(null != cur.pre && null != cur.next){
cur.pre.next = cur.next;
cur.next.pre = cur.pre;
}else if(null != cur.pre){
cur.pre.next = null;
}
cur.pre = null;
cur.next = head;
head.pre = cur;
head = cur;
return cur;
}
cur = cur.next;
}
throw new NullPointerException("this key not find");
}
2.基于LinkedHashMap
private volatile Map<String,String> lruMap;
private int cacheSize;
public LRUcache(int initSize){
this.cacheSize = initSize;
this.lruMap = new LinkedHashMap<String,String>(initSize,0.75f,true){
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
//size()获取map中当前元素数量,和初始设置的值做比较
//超过预设则删除 eldest(年龄最大的)
return size() > LRUcache.this.cacheSize;
}
};
}
public String get(String inKey){
if(inKey.isEmpty() || this.lruMap.isEmpty()){
return null;
}
for(String key : lruMap.keySet()){
if(key.equals(inKey)){
return lruMap.get(key);
}
}
return null;
}
public synchronized boolean put(String key,String value){
this.lruMap.put(key,value);
return true;
}