package com.coding2017.basic;
public class LinkedList implements List {
private Node head;
private Node tail;
private int size;
public void add(Object o) {
addLast(o);
}
public void add(int index, Object o) {
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
}
if (index == size) {
addLast(o);
} else if (index == 0) {
addFirst(o);
} else {
Node node = new Node(o);
Node prevNode = getNode(index - 1);
Node nextNode = prevNode.next;
prevNode.next = node;
node.prev = prevNode;
nextNode.prev = node;
node.next = nextNode;
size++;
}
}
private Node getNode(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
Node node = head;
for (int j = 0; j < index; j++) {
node = node.next;
}
return node;
}
public Object get(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
return getNode(index).data;
}
public Object remove(int index) {
if (index < 0 || index >= size) {
throw new IndexOutOfBoundsException();
}
if (index == 0) {
return removeFirst();
} else if (index == size - 1) {
return removeLast();
} else {
Node node = getNode(index);
node.prev.next = node.next;
node.next.prev = node.prev;
size--;
return node.data;
}
}
public int size() {
return size;
}
public void addFirst(Object o) {
Node node = new Node(o);
if (size == 0) {
head = node;
tail = node;
} else {
head.prev = node;
node.next = head;
head = node;
}
size++;
}
public void addLast(Object o) {
if (size == 0) {
addFirst(o);
} else {
Node node = new Node(o);
tail.next = node;
node.prev = tail;
tail = node;
size++;
}
}
public Object removeFirst() {
if (size == 0) {
throw new IndexOutOfBoundsException();
}
Node node = head;
if (size == 1) {
head = null;
tail = null;
size--;
} else {
head.next.prev = null;
head = head.next;
size--;
}
return node.data;
}
public Object removeLast() {
if (size == 0) {
throw new IndexOutOfBoundsException();
}
if (size == 1) {
return removeFirst();
}
Node node = tail;
tail.prev.next = null;
tail = tail.prev;
size--;
return node.data;
}
public Iterator iterator() {
return new LinkedListIterator();
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("[");
if (size > 0) {
builder.append(get(0));
}
for(Node node = head.next; node != null; node = node.next) {
builder.append(", ").append(node.data);
}
builder.append("]");
return builder.toString();
}
private static class Node {
private Object data;
private Node next;
private Node prev;
public Node() {}
private Node(Object data) {
this.data = data;
}
}
private class LinkedListIterator implements Iterator {
private Node node;
public LinkedListIterator() {
this.node = LinkedList.this.head;
}
@Override
public boolean hasNext() {
return node != null;
}
@Override
public Object next() {
Node temp = node;
node = node.next;
return temp.data;
}
}
}