Implemented QueuedLinkedList
This commit is contained in:
parent
52039e9804
commit
2e1b50c96c
@ -0,0 +1,109 @@
|
|||||||
|
package ru.dragonestia.picker.service.impl.collection;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class QueuedLinkedList<ITEM extends QueuedLinkedList.Item> {
|
||||||
|
|
||||||
|
private Node<ITEM> first;
|
||||||
|
private Node<ITEM> last;
|
||||||
|
private Node<ITEM> cursor;
|
||||||
|
private final Map<String, Node<ITEM>> itemMap = new HashMap<>();
|
||||||
|
|
||||||
|
public void add(ITEM item) {
|
||||||
|
if (itemMap.containsKey(item.getId())) return;
|
||||||
|
|
||||||
|
Node<ITEM> node = new Node<>(item);
|
||||||
|
if (first == null) {
|
||||||
|
first = node;
|
||||||
|
last = first;
|
||||||
|
} else {
|
||||||
|
node.prev = last;
|
||||||
|
last.next = node;
|
||||||
|
last = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemMap.put(item.getId(), node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(ITEM item) {
|
||||||
|
if (!itemMap.containsKey(item.getId())) return;
|
||||||
|
|
||||||
|
var node = itemMap.get(item.getId());
|
||||||
|
itemMap.remove(item.getId());
|
||||||
|
node.removed = true;
|
||||||
|
|
||||||
|
if (node.prev == null) { // first element
|
||||||
|
first = node.next;
|
||||||
|
if (first != null) {
|
||||||
|
first.prev = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.next == null) { // last element
|
||||||
|
last = node.prev;
|
||||||
|
if (last != null) {
|
||||||
|
last.next = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.next != null && node.prev != null) { // middle element
|
||||||
|
var prev = node.prev;
|
||||||
|
var next = node.next;
|
||||||
|
|
||||||
|
prev.next = next;
|
||||||
|
next.prev = prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return itemMap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetCursor() {
|
||||||
|
cursor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITEM pick() {
|
||||||
|
if (first == null) {
|
||||||
|
throw new RuntimeException("List is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cursor == null) cursor = first;
|
||||||
|
|
||||||
|
Node<ITEM> item = cursor;
|
||||||
|
while (item != null && item.removed) {
|
||||||
|
item = item.next;
|
||||||
|
}
|
||||||
|
if (item == null) item = first;
|
||||||
|
|
||||||
|
cursor = item.next;
|
||||||
|
return item.object;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Node<ITEM extends Item> {
|
||||||
|
|
||||||
|
private final ITEM object;
|
||||||
|
private Node<ITEM> prev, next;
|
||||||
|
private boolean removed = false;
|
||||||
|
|
||||||
|
public Node(ITEM object) {
|
||||||
|
this.object = object;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "{Node id=%s, prev=%s, next=%s, removed=%s }".formatted(
|
||||||
|
object.getId(),
|
||||||
|
prev == null? null : prev.object.getId(),
|
||||||
|
next == null? null : next.object.getId(),
|
||||||
|
removed
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Item {
|
||||||
|
|
||||||
|
String getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
package ru.dragonestia.picker.collection;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import ru.dragonestia.picker.service.impl.collection.QueuedLinkedList;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
public class QueuedLinkedListTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testQueuedLinkedList() {
|
||||||
|
var list = new QueuedLinkedList<Item>();
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
list.add(new Item(Integer.toString(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
printList(list);
|
||||||
|
|
||||||
|
var removed = new HashSet<String>();
|
||||||
|
for (int i = 5; i < 8; i++) {
|
||||||
|
var id = Integer.toString(i);
|
||||||
|
|
||||||
|
list.remove(new Item(id));
|
||||||
|
System.out.println("Removed: " + id);
|
||||||
|
removed.add(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
printList(list);
|
||||||
|
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
var item = list.pick();
|
||||||
|
|
||||||
|
System.out.println("Picked: " + item.getId());
|
||||||
|
Assertions.assertFalse(removed.contains(item.getId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void printList(QueuedLinkedList<Item> list) {
|
||||||
|
list.resetCursor();
|
||||||
|
|
||||||
|
var sb = new StringBuilder("List(" + list.size() + "): ");
|
||||||
|
for (int i = 0, n = list.size(); i < n; i++) {
|
||||||
|
sb.append(i);
|
||||||
|
if (i + 1 != n) sb.append(", ");
|
||||||
|
}
|
||||||
|
System.out.println(sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Item implements QueuedLinkedList.Item {
|
||||||
|
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
public Item(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user