本文已参与「新人创作礼」活动,一起开启掘金创作之路。
背景:
突发奇想在我的小平台上添加一个文件下载排行榜,类似于百度的热搜(如下图)。
方案
使用LRU算法实现,该方案就是在内存中维护一个双向链表。将页面准备展示的排行榜的最小名次(例如:上图中的15就是最小名词)作为链表的固定长度,将前台每次下载的文件名称都插入到链表的头部,如果插入的内容超过链表的长度,则把链表的尾节点删除,用以保证链表的长度不变,这样就自然的形成了一个排行榜,最新的下载永远在前边。
代码实现: 1、Node节点
package com.cz.commons.rank;
/**
* 节点(该节点用于后续构建双向链表)
* @program: PostGirl-panent
* @description: Node
* @author: Cheng Zhi
* @create: 2021-09-23 16:28
**/
public class Node {
public Object key, val;
public Node next; // 下一个节点
public Node prev; // 当前节点
public Node(Object k, Object v) {
this.key = k;
this.val = v;
}
}
复制代码
Rank排行榜
package com.cz.commons.rank;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 构造排行榜列表,使用双向链表实现
* @program: PostGirl-panent
* @description: Rank
* @author: Cheng Zhi
* @create: 2021-09-23 16:30
**/
@Component
public class Rank<K,V> {
private int capcity = 10; // 总容量
private int currentSize = 0; // 当前容量
private Node firstNode; // 头节点
private Node lastNode; // 尾节点
private Map<K,Node> caches = new HashMap<K,Node>(10); // 榜单
/**
* 新增节点(先判断榜单上是否存在该节点,如果存在,则排名提升到第一,如果不存在,插入到链表头,同时删除尾节点)
* @param key
* @param value
*/
public void add(K key, V value) {
Node node = caches.get(key);
if (node == null) {
// 新增节点
if (caches.size() >= capcity) {
// 移除最后一个节点
caches.remove(lastNode.key);
// 组织移除后的节点关系
lastNode = lastNode.prev;
lastNode.next = null;
}
// 插入新节点
node = new Node(key, value);
// 组织插入后的节点关系
node.next = firstNode;
if (node.next == null) {
lastNode = node;
} else {
node.next.prev = node;
}
firstNode = node;
currentSize ++;
} else {
// 插入已存在的节点
if (node == firstNode) {
return;
}
node.val = value;
if (node.prev != null) {
node.prev.next = node.next;
}
if (node.next != null) {
node.next.prev = node.prev;
}
node.next = firstNode;
node.next.prev = node;
firstNode = node;
}
caches.put(key, node);
}
/**
* 移除节点(先判断榜单上是否存在该节点,如果存在则删除同时改变该节点的前驱和后继)
* @param key
*/
public void remove(K key) {
Node node = caches.get(key);
if (node == null) {
return;
}
node.prev.next = node.next;
if (node.next != null) {
node.next.prev = node.prev;
}
caches.remove(key);
}
/**
* 获取榜单
*/
public List<String> getRank() {
List<String> lists = new ArrayList<String>();
Node node = firstNode;
while (node != null) {
lists.add((String) node.val);
node = node.next;
}
return lists;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
Node node = firstNode;
while (node != null) {
sb.append(String.format("%s:%s ", node.key, node.val));
node = node.next;
}
return sb.toString();
}
}
复制代码