LRUCache的链表+HashMap实现

LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是如果数据最近被访问过,那么将来被访问的几率也更高。

public class LRUCache<K,V> {
	
	static class Node{
		Node pre;
		Node next;
		Object key;
		Object value;
	}

	/**当前缓存对象数量*/
	private int currentCacheSize;
	/**缓存容量*/
	private int cacheCapcity;
	/**缓存 容器*/
	private Map<K, Node> caches;
	/**(实现双链表)链表头*/
	private Node first;
	/**(实现双链表)链表尾*/
	private Node last;

	public LRUCache(int size) {
		this.currentCacheSize = 0;
		this.cacheCapcity = size;
		this.caches = new HashMap<K,Node>(size);
	}
	
	/***
	 * 利用链表和HashMap:
	 * 当需要插入新的数据项的时候,如果新数据项在链表中存在(一般称为命中),则把该节点移到链表头部,
	 * 如果不存在,则新建一个节点,放到链表头部,若缓存满了,则把链表最后一个节点删除即可。
	 */
	public void put(K k,V v) {
		Node node = caches.get(k);
		if(null == node) {
			if(caches.size() >= cacheCapcity) {
				caches.remove(last.key);//将最少使用的节点删除
				removeLast();
			}
			currentCacheSize ++;
			node = new Node();
			node.key = k;
		}
		node.value = v;
		moveToFirst(node);//将最新使用的节点放在链表头,表示最新使用的。
		caches.put(k, node);
	}

	/****
	 * 在访问数据的时候,如果数据项在链表中存在,则把该节点移到链表头部
	 */
	public Object get(K k) {
		Node node = caches.get(k);
		if(null == node) {
			return null;
		}
		moveToFirst(node);
		return node.value;
	}
	
	/***
	 * 移动到链表头,表示这个节点是最新使用过的
	 * @author ZHEN
	 * 2019年5月16日
	 */
	private void moveToFirst(Node node) {
		if(first == node) {
			return;
		}
		if(null != node.next) {
			node.next.pre = node.pre;
		}
		if(null != node.pre) {
			node.pre.next = node.next;
		}
		if(node == last) {
			last = last.pre;
		}
		if(null == first || null == last) {
			first = last = node;
			return;
		}
		node.next = first;
		first.pre = node;
		first = node;
		first.pre = null;
	}

	/**
	 * 删除链表尾部节点  表示 删除最少使用的缓存对象
	 * @author ZHEN
	 * 2019年5月16日
	 */
	private void removeLast() {//链表尾不为空,则将链表尾指向null. 删除链表尾(删除最少使用的缓存对象)  
		if(null != last) {
			last = last.pre;
			if(null == last) {
				first = null;
			}else {
				last.next = null;
			}
		}
	}
	
	public void clear() {
		first = null;
		last = null;
		caches.clear();
	}
	
	public Object remove(K k) {
		Node node = caches.get(k);
		if(null != node) {
			if(null != node.pre) {
				node.pre.next = node.next;
			}
			if(null != node.next) {
				node.next.pre = node.pre;
			}
			if(node == first) {
				first = node.next;
			}
			if(node == last) {
				last = node.pre;
			}
		}
		return caches.remove(k);//HashMap  remove
	}
	
	public static void main(String[] args) {
		
		LRUCache<Object, Object> lruCache = new LRUCache<>(3);
		
		Object remove = lruCache.remove("k1");
		
		System.out.println(remove);
		
		lruCache.put("k1", "v1");
		lruCache.put("k2", "v2");
		lruCache.put("k3", "v3");
		lruCache.put("k4", "v4");
		
		System.out.println(lruCache.caches);
		System.out.println(lruCache.first);
		lruCache.get("k2");
		
		System.out.println(lruCache.first);
	}
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值