什么是lru算法
内存淘汰机制:
- FIFO(First in,First out):队列,也就是先进先出的数据结构
- LFU(Least Frequently Used):访问最常用的
- LRU(Least Recently Used):访问最近访问过的,热点命中
单链表实现
实现一个单链表,包括增删查改的方法。
/**
* @Auther: allen
* @Date: 2019/8/22 14:40
* @Description: 单链表
*/
public class LinkedList<T> {
/**
* 头节点
*/
protected Node head;
/**
* 集合大小
*/
protected int size;
public LinkedList() {
this.size = 0;
}
class Node{
T data;
Node next;
public Node(T data, Node next) {
this.data = data;
this.next = next;
}
}
//增加
/**
* 向链表头部添加元素
* @param data
*/
protected void put(T data){
Node node = head;
Node curNode = new Node(data, head);
head = curNode;
size ++;
}
/**
* 向链表指定下标添加元素
* @param index
* @param data
*/
protected void put(int index, T data){
checkPointIndex(index);
//如果index等于0,直接调用put方法
if ( index == 0 ){
put(data);
return;
}
Node previous = head;
Node cur = head;
for (int i = 0; i < index; i++) {
previous = cur;
cur = cur.next;
}
Node node = new Node( data, cur);
previous.next = node;
size++;
}
/**
* 检查下标是否越界
* @param index
*/
protected void checkPointIndex(int index) {
if( !( index >= 0 && index <= size )) {
throw new IndexOutOfBoundsException("index:" + index + ", size:" + size);
}
}
//删除
/**
* 移除链表头部元素
* @return
*/
protected T remove(){
if( head != null ){
Node node = head;
head = node.next;
node.next = null; //help gc
size--;
return node.data;
}
return null;
}
/**
* 移除链表指定下标元素
* @param index
* @return
*/
protected T remove(int index){
checkPointIndex(index);
Node pervious = head;
Node cur = head;
for (int i = 0; i < index; i++) {
pervious = cur;
cur = cur.next;
}
pervious.next = cur.next;
cur.next = null; //help gc
size--;
return cur.data;
}
/**
* 移除链表最后一个元素
* @return
*/
protected T removeLast(){
if( head != null ){
Node pervious = head;
Node cur = head;
while ( cur.next != null ){
pervious = cur;
cur = cur.next;
}
cur.next = null;
size --;
return cur.data;
}
return null;
}
//修改
/**
* 修改链表指定下标元素
* @param index
* @param data
*/
protected void set(int index, T data) throws Exception {
checkPointIndex(index);
if( head == null ){
throw new Exception("链表为空,不能修改");
}
Node cur = head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
cur.data = data;
}
//查询
/**
* 获取链表头部元素
* @return
*/
protected T get(){
if( head != null ){
return head.data;
}else {
return null;
}
}
/**
* 获取链表指定下标元素
* @param index
* @return
*/
protected T get(int index) throws Exception {
checkPointIndex(index);
if( head == null ){
throw new Exception("链表为空,获取元素失败");
}
Node cur = head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
return cur.data;
}
@Override
public String toString() {
Node cur = head;
for (int i = 0; i < size; i++) {
System.out.print(cur.data + " ");
cur = cur.next;
}
System.out.println();
return super.toString();
}
public static void main(String[] args) throws Exception{
LinkedList<Integer> list = new LinkedList<Integer>();
for (int i = 0; i < 5; i++) {
list.put(i);
}
list.toString();
//list.set(0,19);
//
//list.toString();
list.put(0,11);
list.toString();
//try {
// list.set(0,4);
//} catch (Exception e) {
// e.printStackTrace();
//}
}
}
基于单链表实现lru算法
- 新数据插入到链表头部
- 当缓存命中(即缓存数据被访问),数据要移到表头
- 当链表满的时候,将链表尾部的数据丢弃
继承单链表,实现例如lru算法。
/**
* @Auther: allen
* @Date: 2019/8/22 17:38
* @Description: 用单链表实现lru缓存算法
*/
public class LruLinkedList<T> extends LinkedList<T> {
/**
* 内存限制大小
*/
private int memory_size;
/**
* 默认的内存限制大小
*/
private static int DEFAULT_CAPACITY = 5;
/**
* @param data
*/
public void lruPut(T data){
//1.新数据插入到链表头部
//2.当链表满的时候,将链表尾部的数据丢弃
if( size >= memory_size ){
removeLast();
put(data);
}else {
put(data);
}
}
/**
*
* @return
*/
public T lruRemove(){
return removeLast();
}
/**
* lruGet方法
* @return
*/
public T lruGet(int index){
//当缓存命中(即缓存数据被访问),数据要移到表头
checkPointIndex(index);
//当集合为空时,读取抛出异常,或者直接返回null
if( head == null ){
return null;
}
Node pervious = head;
Node cur = head;
for (int i = 0; i < index; i++) {
pervious = cur;
cur = cur.next;
}
//保存返回结果
T result = cur.data;
//把当前节点移到头节点
//移除当前节点
pervious.next = cur.next;
//把当前节点移到表头
cur.next = head;
//保存头节点信息
head = cur;
return result;
}
public static void main(String[] args) {
LruLinkedList<Integer> lruList = new LruLinkedList<Integer>();
for (int i = 0; i < 5; i++) {
lruList.lruPut(i);
}
lruList.toString();
lruList.lruGet(3);
lruList.toString();
}
public LruLinkedList() {
this(DEFAULT_CAPACITY);
}
public LruLinkedList(int memory_size) {
this.memory_size = memory_size;
}
}