1
+ import java .util .HashMap ;
2
+
3
+ /**
4
+ * @Description:基于散列表的LRU算法
5
+ * @Author: Hoda
6
+ * @Date: Create in 2019-08-09
7
+ * @Modified By:
8
+ * @Modified Date:
9
+ */
10
+ public class LRUBaseHashTable <K , V > {
11
+
12
+ /**
13
+ * 默认链表容量
14
+ */
15
+ private final static Integer DEFAULT_CAPACITY = 10 ;
16
+
17
+ /**
18
+ * 头结点
19
+ */
20
+ private DNode <K , V > headNode ;
21
+
22
+ /**
23
+ * 尾节点
24
+ */
25
+ private DNode <K , V > tailNode ;
26
+
27
+ /**
28
+ * 链表长度
29
+ */
30
+ private Integer length ;
31
+
32
+ /**
33
+ * 链表容量
34
+ */
35
+ private Integer capacity ;
36
+
37
+ /**
38
+ * 散列表存储key
39
+ */
40
+ private HashMap <K , DNode <K , V >> table ;
41
+
42
+ /**
43
+ * 双向链表
44
+ */
45
+ static class DNode <K , V > {
46
+
47
+ private K key ;
48
+
49
+ /**
50
+ * 数据
51
+ */
52
+ private V value ;
53
+
54
+ /**
55
+ * 前驱指针
56
+ */
57
+ private DNode <K , V > prev ;
58
+
59
+ /**
60
+ * 后继指针
61
+ */
62
+ private DNode <K , V > next ;
63
+
64
+ DNode () {
65
+ }
66
+
67
+ DNode (K key , V value ) {
68
+ this .key = key ;
69
+ this .value = value ;
70
+ }
71
+
72
+ }
73
+
74
+ public LRUBaseHashTable (int capacity ) {
75
+ this .length = 0 ;
76
+ this .capacity = capacity ;
77
+
78
+ headNode = new DNode <>();
79
+
80
+ tailNode = new DNode <>();
81
+
82
+ headNode .next = tailNode ;
83
+ tailNode .prev = headNode ;
84
+
85
+ table = new HashMap <>();
86
+ }
87
+
88
+ public LRUBaseHashTable () {
89
+ this (DEFAULT_CAPACITY );
90
+ }
91
+
92
+ /**
93
+ * 新增
94
+ *
95
+ * @param key
96
+ * @param value
97
+ */
98
+ public void add (K key , V value ) {
99
+ DNode <K , V > node = table .get (key );
100
+ if (node == null ) {
101
+ DNode <K , V > newNode = new DNode <>(key , value );
102
+ table .put (key , newNode );
103
+ addNode (newNode );
104
+
105
+ if (++length > capacity ) {
106
+ DNode <K , V > tail = popTail ();
107
+ table .remove (tail .key );
108
+ length --;
109
+ }
110
+ } else {
111
+ node .value = value ;
112
+ moveToHead (node );
113
+ }
114
+ }
115
+
116
+ /**
117
+ * 将新节点加到头部
118
+ *
119
+ * @param newNode
120
+ */
121
+ private void addNode (DNode <K , V > newNode ) {
122
+ newNode .next = headNode .next ;
123
+ newNode .prev = headNode ;
124
+
125
+ headNode .next .prev = newNode ;
126
+ headNode .next = newNode ;
127
+ }
128
+
129
+ /**
130
+ * 弹出尾部数据节点
131
+ */
132
+ private DNode <K , V > popTail () {
133
+ DNode <K , V > node = tailNode .prev ;
134
+ removeNode (node );
135
+ return node ;
136
+ }
137
+
138
+ /**
139
+ * 移除节点
140
+ *
141
+ * @param node
142
+ */
143
+ private void removeNode (DNode <K , V > node ) {
144
+ node .prev .next = node .next ;
145
+ node .next .prev = node .prev ;
146
+ }
147
+
148
+ /**
149
+ * 将节点移动到头部
150
+ *
151
+ * @param node
152
+ */
153
+ private void moveToHead (DNode <K , V > node ) {
154
+ removeNode (node );
155
+ addNode (node );
156
+ }
157
+
158
+ /**
159
+ * 获取节点数据
160
+ *
161
+ * @param key
162
+ * @return
163
+ */
164
+ public V get (K key ) {
165
+ DNode <K , V > node = table .get (key );
166
+ if (node == null ) {
167
+ return null ;
168
+ }
169
+ moveToHead (node );
170
+ return node .value ;
171
+ }
172
+
173
+ /**
174
+ * 移除节点数据
175
+ *
176
+ * @param key
177
+ */
178
+ public void remove (K key ) {
179
+ DNode <K , V > node = table .get (key );
180
+ if (node == null ) {
181
+ return ;
182
+ }
183
+ removeNode (node );
184
+ length --;
185
+ }
186
+
187
+ private void printAll () {
188
+ DNode <K , V > node = headNode .next ;
189
+ while (node .next != null ) {
190
+ System .out .print (node .value + "," );
191
+ node = node .next ;
192
+ }
193
+ System .out .println ();
194
+ }
195
+ }
0 commit comments