public class List<E extends Comparable<E>> {
public void add(E item)
class SortedList<E extends Comparable<E>> {
private Node<E> head;
private int size;
public void add(E item) {
Node<E> curr = head;
Node<E> beforeCurr = null;
//advance curr until null or pointing to first node >= item
while (curr != null && curr.getData().compareTo(item) < 0) {
beforeCurr = curr;
curr = curr.getNext();
}
if (beforeCurr == null) { //or: if (curr == this.head) {
//adding at head of list
this.head = new Node<E>(item, this.head);
}else {
beforeCurr.setNext(new Node<E>(item, curr));
}
this.size++;
}
//...other methods...
}
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> {
private E data;
private DLNode<E> next;
private DLNode<E> prev;
public DLNode(DLNode<E> prev, E data, DLNode<E> next) {
this.data = data;
this.prev = prev;
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.
public class DLNode<E> extends Node<E> {
private DLNode<E> prev;
public DLNode(DLNode<E> prev, E data, DLNode<E> next) {
super(data, next);
this.prev = prev;
}
public DLNode(E data) {
this(null, data, null);
}
public DLNode<E> getPrevious() {
return prev;
}
public void setPrevious(DLNode<E> prev) {
this.prev = prev;
}
}
This can be a little problematic to use in practice, though, since getNext() returns a Node while getPrevious() returns a DLNode. This means you can't do something like node.getNext().getPrevious() without casting.
public String toString() {
String str = "";
DLNode<E> curr = this.sentinel.getNext();
while (curr != this.sentinel) {
str += curr.getData() + " "; //crude toString formatting
curr = curr.getNext();
}
return str;
}
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(); } //...nested LinkedListIterator class here... }
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()
}
}
}
Wouldn't need beforeLast if we had a doubly-linked list.