33import java .util .HashMap ;
44import java .util .concurrent .ThreadLocalRandom ;
55
6+ //двухсвязный список
67class Node <Value > {
8+ //ключ списка
79 int key ;
10+
11+ //абстрактное значение
812 Value value ;
913
14+ //счетчик обращений к элементу
1015 int cnt ;
1116
17+ //указатель на предыдущий элемент
1218 Node prev ;
19+
20+ //указатель на следующий элемент
1321 Node next ;
1422
1523 public Node (int key , Value value ){
@@ -18,38 +26,56 @@ public Node(int key, Value value){
1826 this .cnt = 1 ;
1927 }
2028
29+ //получить значение из списка
2130 public Value getValue () {
31+ //увеличиваем счетчик обращений
2232 cnt ++;
2333 return value ;
2434 }
2535
36+ //установить значение
2637 public void setValue (Value val ) {
2738 this .value = val ;
39+ //также увеличиваем счетчик
2840 cnt ++;
2941 } //setValue
3042} //Node
3143
3244
3345public class Lru <Value > {
3446
47+ //доступной число элементов в кэше
3548 int capacity ;
3649
50+ //хэш массив элементов для быстрого доступа
3751 HashMap <Integer , Node > map ;
3852
53+ //указатель на начало (горячие элементы)
3954 Node head = null ;
55+
56+ //указатель на середину (начало холодных элементов)
4057 Node cold = null ;
58+
59+ //указатель на конец (самый редкоиспользуемый)
4160 Node end = null ;
4261
62+ //число элементов в кэше
4363 int cnt ;
4464
65+
66+ //конкструктор с числом элементов в кэше
4567 public Lru (int capacity ) {
4668 this .capacity = capacity ;
4769
70+ //хэш массив создаем с нужным числом секций = загруженности
4871 map = new HashMap <Integer , Node >(capacity );
4972 }
5073
74+ //получить элемент из кэша
5175 public Value get (int key ) {
76+ //быстрое извлечение их хэш массива
5277 if (map .containsKey (key )) {
78+ //и инкремент счетчика обращений
5379 return (Value ) map .get (key ).getValue ();
5480 }
5581
@@ -61,17 +87,23 @@ protected void addHead(Node n) {
6187
6288 //первый элемент
6389 if (this .head == null ) {
90+ //устанавливаем начало и конец = элементу
6491 this .head = n ;
6592 this .end = n ;
6693 } else {
6794
6895 //вставляем вначало
96+
97+ //следующий для нового элемента = начало списка
6998 n .next = this .head ;
99+
100+ //предыдущий для начала списка = новый элемент
70101 this .head .prev = n ;
71102 this .head = n ;
72103
73104 //второй элемент
74105 if (this .end .prev == null ) {
106+ //предыдущий для конца = новый элемент
75107 this .end .prev = n ;
76108 }
77109 }
@@ -81,22 +113,31 @@ protected void addHead(Node n) {
81113 this .cold = n ;
82114 }
83115
116+ //счетчик элементов + 1
84117 cnt ++;
85118 } //addHead
86119
87120 //вконце малопопулярный блок
88121 protected void addColdUnPop (Node n ) {
89122 //удаляем конец
123+
124+ //из хэш массива
90125 map .remove (this .end .key );
126+
127+ //и делаем концом списка = предыдущий элемент
91128 this .end = this .end .prev ;
92129 this .end .next = null ;
93130
94131 //у старой середины изменяем счетчик на 1
95132 this .cold .cnt = 1 ;
96133
97134 //новый блок в середину = cold
135+
136+ //проставляем ссылки у нового элемента
98137 n .prev = this .cold .prev ;
99138 n .next = this .cold ;
139+
140+ //и разрываем связи и соседей
100141 n .prev .next = n ;
101142 n .next .prev = n ;
102143 this .cold = n ;
@@ -108,7 +149,9 @@ protected void addColdPop(int key, Value value) {
108149 this .end .cnt = this .end .cnt / 2 ;
109150
110151 //открепляем конец
111- Node n = this .end ;
152+ Node n = this .end ;
153+
154+ //и делаем концом списка = предыдущий элемент
112155 this .end = this .end .prev ;
113156 this .end .next = null ;
114157
@@ -127,12 +170,16 @@ protected void addColdPop(int key, Value value) {
127170 } //addColdPop
128171
129172 public void set (int key , Value value ) {
173+ //если элемент по ключу уже есть, то заменяем значение
130174 if (map .containsKey (key )) {
131175 map .get (key ).setValue (value );
132176 } else {
177+ //новый элемент
133178 Node created = new Node (key , value );
134179
180+ //если в буфере еще есть место
135181 if (cnt < capacity ) {
182+ //просто вставляем в начало
136183 addHead (created );
137184 } else {
138185 //свободного места нет
@@ -147,11 +194,13 @@ public void set(int key, Value value) {
147194 }
148195 } //else
149196
197+ //добавляем элемент в хэш массив
150198 map .put (key , created );
151199
152200 } //else
153201 } //set
154202
203+ //вывод двусвязного списка на экран
155204 public void dump () {
156205 System .out .print ("cnt: " + this .cnt + " (cap: " + this .capacity + "): " );
157206
0 commit comments