Skip to content

Commit 5f6d8e5

Browse files
committed
Сделать бесконечную историю со скоростью доступа О(1).
1 parent 6984829 commit 5f6d8e5

File tree

4 files changed

+274
-24
lines changed

4 files changed

+274
-24
lines changed

src/ru/alexgur/kanban/service/HistoryManager.java

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ public interface HistoryManager {
1010

1111
void clear();
1212

13+
void remove(int id);
14+
1315
List<Task> getHistory();
1416

1517
}
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,104 @@
11
package ru.alexgur.kanban.service;
22

33
import java.util.ArrayList;
4+
import java.util.Collections;
5+
import java.util.HashMap;
46
import java.util.List;
57

68
import ru.alexgur.kanban.model.Task;
79

810
public class InMemoryHistoryManager implements HistoryManager {
911

10-
public static final int HISTORY_MAX_SIZE = 10;
11-
12-
private ArrayList<Task> history = new ArrayList<>();
12+
private Node head;
13+
private Node tail;
14+
private HashMap<Integer, Node> history = new HashMap<>();
1315

1416
@Override
1517
public void clear() {
1618
clearImpl();
1719
}
1820

21+
@Override
22+
public void remove(int id) {
23+
removeImpl(id);
24+
}
25+
1926
@Override
2027
public void add(Task task) {
2128
addImpl(task);
2229
}
2330

2431
@Override
2532
public List<Task> getHistory() {
26-
return getHistoryImpl();
33+
List<Task> listTasks = new ArrayList<>();
34+
for (Node node : getTasks()) {
35+
listTasks.add(node.getTask());
36+
}
37+
return listTasks;
38+
}
39+
40+
private Node linkLast(Task task) {
41+
final Node oldtail = tail;
42+
final Node newNode = new Node(oldtail, task, null);
43+
tail = newNode;
44+
if (oldtail == null) {
45+
head = newNode;
46+
} else {
47+
oldtail.setNext(newNode);
48+
}
49+
return newNode;
50+
}
51+
52+
private ArrayList<Node> getTasks() {
53+
ArrayList<Node> nodes = new ArrayList<>();
54+
Node currentNode = head;
55+
while (currentNode != null) {
56+
nodes.add(currentNode);
57+
currentNode = currentNode.getNext();
58+
}
59+
Collections.reverse(nodes);
60+
return nodes;
2761
}
2862

2963
private void addImpl(Task task) {
3064
if (task != null) {
31-
history.add(task);
32-
if (history.size() > HISTORY_MAX_SIZE) {
33-
history.remove(0);
65+
if (history.containsKey(task.getId())) {
66+
Node node = history.remove(task.getId());
67+
removeNode(node);
3468
}
69+
Node node = linkLast(task);
70+
history.put(task.getId(), node);
71+
}
72+
}
73+
74+
private void removeNode(Node node) {
75+
Node prev = node.getPrev();
76+
Node next = node.getNext();
77+
78+
if (prev != null && next != null) {
79+
// Удаляетяся элемент в середине списка
80+
next.setPrev(prev);
81+
prev.setNext(next);
82+
} else if (prev == null && next != null) {
83+
// Удаляетяся первый элемент
84+
head = next;
85+
next.setPrev(null);
86+
} else if (prev != null && next == null) {
87+
// Удаляетяся последний элемент
88+
tail = prev;
89+
prev.setNext(null);
3590
}
91+
92+
history.remove(node.getTask().getId());
3693
}
3794

38-
private List<Task> getHistoryImpl() {
39-
List<Task> res = history;
40-
return List.copyOf(res);
95+
private void removeImpl(int id) {
96+
history.remove(id);
4197
}
4298

4399
private void clearImpl() {
100+
head = null;
101+
tail = null;
44102
history.clear();
45103
}
46-
47104
}
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package ru.alexgur.kanban.service;
2+
3+
import ru.alexgur.kanban.model.Task;
4+
5+
public class Node {
6+
private Task task;
7+
private Node next;
8+
private Node prev;
9+
10+
public Node(Node prev, Task task, Node next) {
11+
this.task = task;
12+
this.next = next;
13+
this.prev = prev;
14+
}
15+
16+
@Override
17+
public int hashCode() {
18+
return task.hashCode();
19+
}
20+
21+
@Override
22+
public boolean equals(Object obj) {
23+
Node other = (Node) obj;
24+
return task.equals(other.task);
25+
}
26+
27+
public Task getTask() {
28+
return task;
29+
}
30+
31+
public void setTask(Task task) {
32+
this.task = task;
33+
}
34+
35+
public Node getNext() {
36+
return next;
37+
}
38+
39+
public void setNext(Node next) {
40+
this.next = next;
41+
}
42+
43+
public Node getPrev() {
44+
return prev;
45+
}
46+
47+
public void setPrev(Node prev) {
48+
this.prev = prev;
49+
}
50+
}

0 commit comments

Comments
 (0)