All Downloads are FREE. Search and download functionalities are using the official Maven repository.

eu.lucaventuri.collections.NodeLinkedList Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
package eu.lucaventuri.collections;

import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * NodeLinkedList that uses Nodes instead of adding values as the Java lists do.
 * As a result, we can add and remove a specific node in O(1), which is our goal.
 * This class is not thread safe, and it is intended to be used from a single thread.
 * In particular it is used as part of the "receive" functionality, so it is called by the actor, which, by definition, runs on a single thread/fiber.
 * Thread safety is achieved using a blocking queue before that.
 */
public class NodeLinkedList implements Iterable {
    private Node head;
    private Node tail;


    @Override
    public Iterator iterator() {
        return new Iterator() {
            private Node cur = head;

            @Override
            public boolean hasNext() {
                return cur != null;
            }

            @Override
            public T next() {
                T value = cur.value;

                cur = cur.next;
                return value;
            }
        };
    }

    public Iterable> asNodesIterable() {
        return new Iterable>() {
            @Override
            public Iterator> iterator() {
                return new Iterator>() {
                    private Node cur = head;

                    @Override
                    public boolean hasNext() {
                        return cur != null;
                    }

                    @Override
                    public Node next() {
                        Node value = cur;

                        cur = cur.next;
                        return value;
                    }
                };
            }
        };
    }

    public Node removeFirstByValue(T value) {
        for (Node node : asNodesIterable()) {
            if (node.value != null && node.value.equals(value)) {
                remove(node);

                return node;
            }
        }

        return null;
    }

    public boolean ieEmpty() {
        return head == null;
    }

    public static class Node {
        public final T value;
        private Node next;
        private Node prev;

        Node(T value) {
            this.value = value;
        }
    }


    private void verify() {
        //assert (tail.get()==null && head.get() == null) || (tail.get() != null && head.get() != null);
    }

    public Node addToTail(T value) {
        verify();

        Node n = new Node<>(value);
        Node prevTail = tail;
        tail = n;
        n.prev = prevTail;

        if (prevTail != null) {
            prevTail.next = n;
        } else
            head = n;

        verify();

        return n;
    }

    public void remove(Node node) {
        verify();

        if (head == node)
            head = node.next;
        if (tail == node)
            tail = node.prev;

        // TODO: it would be nice to assert that it is part of this list...
        if (node.prev != null)
            node.prev.next = node.next;

        if (node.next != null)
            node.next.prev = node.prev;

        node.prev = node.next = null;

        verify();
    }

    public Node removeHeadNode() {
        verify();

        // TODO: it would be nice to assert that it is part of this list...
        Node prevHead = head;

        if (prevHead == null)
            return null;

        // Head available
        Node newHead = prevHead.next;

        head = newHead;

        if (newHead != null)
            newHead.prev = null;
        else
            tail = null;

        verify();

        return prevHead;
    }

    public T removeHead() {
        Node node = removeHeadNode();

        return node == null ? null : node.value;
    }

    public T peekHead() {
        Node node = head;

        return node == null ? null : node.value;
    }

    public T peekTail() {
        Node node = tail;

        return node == null ? null : node.value;
    }

    List asListFromHead() {
        List list = new ArrayList<>();
        Node n = head;

        while (n != null) {
            list.add(n.value);
            n = n.next;
        }

        return list;
    }

    List asListFromTail() {
        List list = new ArrayList<>();
        Node n = tail;

        while (n != null) {
            list.add(n.value);
            n = n.prev;
        }

        return list;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy