想着实现缓存,只是提供下思路,还有很多的问题,无法进行应用
/**
* 本质上是通过双链表 + 哈希表来实现的
* 可以再加上过期时间,根据过期时间删除
*/
public class LRUCache {
// 链表节点的定义
class LRUNode{
String key;
Object value;
LRUNode next;
LRUNode pre;
// 假设都是毫秒
Long expireTime;
public LRUNode(String key, Object value,Long expireTime) {
this.key = key;
this.value = value;
this.expireTime = expireTime;
}
@Override
public String toString() {
return "LRUNode{" +
"key='" + key + '\'' +
", value=" + value +
", expireTime=" + expireTime +
'}';
}
}
Map<String, LRUNode> map = new HashMap<>();
LRUNode head;
LRUNode tail;
// 缓存最大容量,我们假设最大容量大于 1,
// 当然,小于等于1的话需要多加一些判断另行处理
int capacity;
public LRUCache(int capacity) {
this.capacity = capacity;
}
public void getAll(){
System.out.println("输出所有map的值");
for (String key : this.map.keySet()){
System.out.println(key + "=============" + this.map.get(key).toString());
}
System.out.println("输出当前node的双向链表的值");
LRUNode temp = head;
while(true){
if (temp == null){
break;
}
System.out.println(temp.toString());
temp = temp.next;
}
}
public synchronized void put(String key, Object value, Long expireTime) {
// 简化处理,如果头部没数据,那么直接加入进去
if (head == null) {
head = new LRUNode(key, value, expireTime);
tail = head;
map.put(key, head);
}
// 如果内部有数据,通过map去查询出数据
LRUNode node = map.get(key);
// 如果node为空,那么往后续去添加
if (node != null) {
// 更新值,直接更新值
node.value = value;
// 更新过期时间
node.expireTime = expireTime == null ? null : (System.currentTimeMillis() + expireTime);
// 把他从链表删除并且插入到头结点
removeAndInsert(node);
} else {
LRUNode tmp = new LRUNode(key, value, expireTime);
// 如果会溢出
if (map.size() >= capacity) {
// 如果溢出了,那么就先查询过期的key进行删除
LRUNode tempDeleteNode = tail;
for (;;){
if (tempDeleteNode == null){
// 如果指针全部循环完成后,还是没有过期的,那么进行一波最后的尾部删除
map.remove(tail.key);
tail = tail.pre;
tail.next = null;
break;
}
if (tempDeleteNode.expireTime != null && tempDeleteNode.expireTime <= System.currentTimeMillis()){
map.remove(tempDeleteNode.key);
// 删除当前的节点
tempDeleteNode.pre.next = tempDeleteNode.next;
// 保证gc回收
tempDeleteNode = null;
break;
}
tempDeleteNode = tempDeleteNode.pre;
}
}
map.put(key, tmp);
// 插入
tmp.next = head;
head.pre = tmp;
head = tmp;
}
}
public Object get(String key) {
LRUNode node = map.get(key);
if (node != null) {
// 把这个节点删除并插入到头结点
removeAndInsert(node);
return node.value;
}
return null;
}
private synchronized void removeAndInsert(LRUNode node) {
// 特殊情况先判断,例如该节点是头结点或是尾部节点
if (node == head) {
return;
} else if (node == tail) {
tail = node.pre;
tail.next = null;
} else {
node.pre.next = node.next;
node.next.pre = node.pre;
}
// 插入到头结点
node.next = head;
node.pre = null;
head.pre = node;
head = node;
}
public static void main(String[] args) {
LRUCache lruCache = new LRUCache(4);
lruCache.put("key1","xxxxx",null);
lruCache.put("key2",1111,null);
// 这个是删除过期时间的
// lruCache.put("key3","yyyyy",2L);
// 这个是删除最后一位的
lruCache.put("key3","yyyyy",null);
lruCache.put("key4","object",null);
lruCache.getAll();
System.out.println("=========================");
lruCache.put("key5", "zzzz",null);
lruCache.getAll();
}
}
参考一个大佬的文章,现在暂时找不到。。。如果有人发现,评论贴一下