Skip to content

Commit

Permalink
Сделать бесконечную историю со скоростью доступа О(1).
Browse files Browse the repository at this point in the history
  • Loading branch information
AlekseyGur committed Nov 23, 2024
1 parent 6984829 commit 5f6d8e5
Show file tree
Hide file tree
Showing 4 changed files with 274 additions and 24 deletions.
2 changes: 2 additions & 0 deletions src/ru/alexgur/kanban/service/HistoryManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public interface HistoryManager {

void clear();

void remove(int id);

List<Task> getHistory();

}
79 changes: 68 additions & 11 deletions src/ru/alexgur/kanban/service/InMemoryHistoryManager.java
Original file line number Diff line number Diff line change
@@ -1,47 +1,104 @@
package ru.alexgur.kanban.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import ru.alexgur.kanban.model.Task;

public class InMemoryHistoryManager implements HistoryManager {

public static final int HISTORY_MAX_SIZE = 10;

private ArrayList<Task> history = new ArrayList<>();
private Node head;
private Node tail;
private HashMap<Integer, Node> history = new HashMap<>();

@Override
public void clear() {
clearImpl();
}

@Override
public void remove(int id) {
removeImpl(id);
}

@Override
public void add(Task task) {
addImpl(task);
}

@Override
public List<Task> getHistory() {
return getHistoryImpl();
List<Task> listTasks = new ArrayList<>();
for (Node node : getTasks()) {
listTasks.add(node.getTask());
}
return listTasks;
}

private Node linkLast(Task task) {
final Node oldtail = tail;
final Node newNode = new Node(oldtail, task, null);
tail = newNode;
if (oldtail == null) {
head = newNode;
} else {
oldtail.setNext(newNode);
}
return newNode;
}

private ArrayList<Node> getTasks() {
ArrayList<Node> nodes = new ArrayList<>();
Node currentNode = head;
while (currentNode != null) {
nodes.add(currentNode);
currentNode = currentNode.getNext();
}
Collections.reverse(nodes);
return nodes;
}

private void addImpl(Task task) {
if (task != null) {
history.add(task);
if (history.size() > HISTORY_MAX_SIZE) {
history.remove(0);
if (history.containsKey(task.getId())) {
Node node = history.remove(task.getId());
removeNode(node);
}
Node node = linkLast(task);
history.put(task.getId(), node);
}
}

private void removeNode(Node node) {
Node prev = node.getPrev();
Node next = node.getNext();

if (prev != null && next != null) {
// Удаляетяся элемент в середине списка
next.setPrev(prev);
prev.setNext(next);
} else if (prev == null && next != null) {
// Удаляетяся первый элемент
head = next;
next.setPrev(null);
} else if (prev != null && next == null) {
// Удаляетяся последний элемент
tail = prev;
prev.setNext(null);
}

history.remove(node.getTask().getId());
}

private List<Task> getHistoryImpl() {
List<Task> res = history;
return List.copyOf(res);
private void removeImpl(int id) {
history.remove(id);
}

private void clearImpl() {
head = null;
tail = null;
history.clear();
}

}
50 changes: 50 additions & 0 deletions src/ru/alexgur/kanban/service/Node.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package ru.alexgur.kanban.service;

import ru.alexgur.kanban.model.Task;

public class Node {
private Task task;
private Node next;
private Node prev;

public Node(Node prev, Task task, Node next) {
this.task = task;
this.next = next;
this.prev = prev;
}

@Override
public int hashCode() {
return task.hashCode();
}

@Override
public boolean equals(Object obj) {
Node other = (Node) obj;
return task.equals(other.task);
}

public Task getTask() {
return task;
}

public void setTask(Task task) {
this.task = task;
}

public Node getNext() {
return next;
}

public void setNext(Node next) {
this.next = next;
}

public Node getPrev() {
return prev;
}

public void setPrev(Node prev) {
this.prev = prev;
}
}
Loading

0 comments on commit 5f6d8e5

Please sign in to comment.