public class MLinkedList<E> {
/**
* Node
*/
private static class Node<E> {
Node<E> prev;
E data;
Node<E> next;
Node(Node<E> prev, E data, Node<E> next) {
this.prev = prev;
this.data = data;
this.next = next;
}
}
private Node<E> first;
private Node<E> last;
private int size;
public void add(E data) {
linkLast(data);
}
public void add(int index, E data) {
link(index, data);
}
private void link(int index, E data) {
if (index == 0) {
linkFirst(data);
return;
}
Node<E> targetNode = node(index);
Node<E> pNode = targetNode.prev;
Node<E> newNode = new Node<>(targetNode.prev, data, targetNode);
pNode.next = newNode;
targetNode.prev = newNode;
size++;
}
private void linkLast(E data) {
Node<E> l = last;
Node<E> newNode = new Node<>(l, data, null);
last = newNode;
if (l == null) {
first = newNode;
} else {
l.next = newNode;
}
size++;
}
public void addLast(E data) {
linkLast(data);
}
public void addFirst(E data) {
linkFirst(data);
}
private void linkFirst(E data) {
Node<E> f = first;
Node<E> newNode = new Node<>(null, data, f);
first = newNode;
if (f == null) {
last = newNode;
} else {
f.prev = newNode;
}
size++;
}
public int size() {
return size;
}
public E get(int index) {
return node(index).data;
}
private Node<E> node(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException();
if (index < size>>2) {
Node<E> node = first;
for (int i = 1; i <= index; i++) {
node = node.next;
}
return node;
} else {
Node<E> node = last;
for (int i = size - 2; i >= index; i--) {
node = node.prev;
}
return node;
}
}
public E remove() {
return removeFirst();
}
public E removeFirst() {
return unlinkFirst();
}
private E unlinkFirst() {
Node<E> f = first;
if (f == null) {
return null;
} else if (size == 1) {
first = null;
last = null;
} else {
first = f.next;
f.next = null;
first.prev = null;
}
size--;
return f.data;
}
public E removeLast() {
return unlinkLast();
}
private E unlinkLast() {
Node<E> l = last;
if (l == null) {
return null;
} else {
last = last.prev;
l.prev = null;
last.next = null;
size--;
return l.data;
}
}
public E remove(int index) {
return unlink(index);
}
private E unlink(int index) {
Node<E> targetNode = node(index);
if (index == 0) {
return unlinkFirst();
} else if (index == size - 1) {
return unlinkLast();
} else {
Node<E> pNode = targetNode.prev;
Node<E> lNode = targetNode.next;
pNode.next = lNode;
lNode.prev = pNode;
targetNode.prev = null;
targetNode.next = null;
size--;
return targetNode.data;
}
}
public void append(MLinkedList<E> mLinkedList) {
if (size == 0) {
first = mLinkedList.first;
last = mLinkedList.last;
size = mLinkedList.size;
} else {
Node<E> lNode = last;
last = mLinkedList.last;
lNode.next = mLinkedList.first;
mLinkedList.first.prev = lNode;
size = size + mLinkedList.size;
}
}
public void addAll(MLinkedList mLinkedList) {
append(mLinkedList);
}
}