package com.coding2017.week4.lru;
/**
* 用双向链表实现LRU算法
*
* @author liuxin
*
*/
public class LRUPageFrame {
private static class Node {
Node prev;
Node next;
int pageNum;
Node() {
}
}
private int capacity;
private Node first;// 链表头
private Node last;// 链表尾
private int size; // 当前个数
public LRUPageFrame(int capacity) {
this.capacity = capacity;
size = 0;
}
/**
* 获取缓存中对象
*
* @param pageNum
* @return
*/
public void access(int pageNum) {
Node node = query(pageNum);
if (node == null) {
Node newNode = new Node();
newNode.pageNum = pageNum;
accessNotExist(newNode);
} else {
accessExist(node);
}
}
private void accessExist(Node node) {
removeNode(node);
addFirst(node);
}
/**
* 此处没有要求传入的node的prev和next, 所以需要自己处理
*
* @param node
*/
private void addFirst(Node node) {
node.prev = null;
node.next = null;
if (first == null) {
first = node;
last = node;
} else {
first.prev = node;
node.next = first;
first = node;
}
size++;
}
/**
* 需要考虑删除的节点是头结点, 或尾节点的情况
*/
private void removeNode(Node node) {
if (node.prev == null) {
first = node.next;
}
if (node.next == null) {
last = node.prev;
}
if (node.prev != null) {
node.prev.next = node.next;
}
if (node.next != null) {
node.next.prev = node.prev;
}
size--;
}
/**
* 如果已经满了, 则挤出去一个, 然后追加
*
* @param node
*/
private void accessNotExist(Node node) {
if (size == capacity) {
removeLast();
}
addFirst(node);
}
private void removeLast() {
last.prev.next = null;
last = last.prev;
size--;
}
private Node query(int pageNum) {
for (Node node = first; node != null; node = node.next) {
if (pageNum == node.pageNum) {
return node;
}
}
return null;
}
public String toString() {
StringBuilder buffer = new StringBuilder();
Node node = first;
while (node != null) {
buffer.append(node.pageNum);
node = node.next;
if (node != null) {
buffer.append(",");
}
}
return buffer.toString();
}
}