public class List<E extends Comparable<E>> {
public void add(E item)
Node<E> before = this.getNode(index - 1); //if sentinel == -1 Node<E> toAdd = new Node<E>(item, before.getNext()); before.setNext(toAdd); this.size++;
public class DLNode<E> extends Node<E> { private E data; private DLNode<E> next; private DLNode<E> prev; public DLNode(E data, DLNode<E> next) { this.data = data; this.next = next; } public DLNode(E data) { this(data, null); } public E getData() { return data; } public void setData(E data) { this.data = data; } public DLNode<E> getNext() { return next; } public void setNext(DLNode<E> next) { this.next = next; } public DLNode<E> getPrevious() { return prev; } public void setPrevious(DLNode<E> prev) { this.prev = prev; } }
Alternatively: could have extended Node to just add previous details.
List<String> list = new List<String>(); //...add some values... for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); }
Basically an object that moves along the list
public class List<E> { //...current contents... public class LinkedListIterator implements java.util.Iterator<E> { //Note: did not redeclare <E> Node<E> next; //Node of item to return on next call to next() public LinkedListIterator() { this.next = head; //refers's to List's head. Explicit: List.this.head } public boolean hasNext() { return next != null; } public E next() { if (next == null) { throw new java.util.NoSuchElementException(); }else { E item = next.getData(); next = next.getNext(); return item; } } public void remove() { //optional: not implemented here throw new UnsupportedOperationException(); } } }//end of List
class List<E> implements Iterable<E> { //...current contents... public java.util.Iterator<E> iterator() { return new LinkedListIterator(); //or: new List<E>.LinkedListIterator(); } }
List<Integer> list = new List<Integer>(); for (int i = 1; i < 10; i++) { list.add(i - 1, i); } //iterator for-each loop (thanks to List implementing Iterable) for (int item : list) { System.out.print(item + " "); } System.out.println(); //basically equivalent using iterator directly int item; for (java.util.Iterator<Integer> iter = list.iterator(); iter.hasNext(); ) { item = iter.next(); System.out.print(item + " "); } System.out.println();
public class LinkedListIterator implements java.util.Iterator<E> { Node<E> next; //Node of item to return on next call to next() Node<E> last; //Node of item returned by last call to next() Node<E> beforeLast; //Node before last, needed for remove() public LinkedListIterator() { this.next = head; //refers's to List's head. Explicit: List.this.head this.last = null; this.beforeLast = null; } public boolean hasNext() { return next != null; } public E next() { if (next == null) { throw new java.util.NoSuchElementException(); }else { E item = next.getData(); //advance along list if (last != null) { beforeLast = last; } last = next; next = next.getNext(); return item; } } public void remove() { if (this.last == null) { //next() not called yet or already removed since call throw new IllegalStateException(); }else { if (beforeLast == null) { //haven't returned second item of list yet, so removing first head = next; }else { beforeLast.setNext(next); } last = null; //so we know we removed since last call to next() } } }
Could use only next
and last
(or similar) if we had a doubly-linked list.