In order to use our linked list with
a for-each-loop:
GenericLinkedList stringList = new GenericLinkedList();
stringList.addFirst("C");
stringList.addFirst("B");
stringList.addFirst("A");
// Use our linked list in a for-each loop
for ( String s : stringList )
System.out.println(s);
our GenericLinkedList class
must implement the
Iterable<T>:
// Implementing this interface allows an object to be
// the target of the "for-each loop" statement.
public interface Iterable<T>
{
public Iterator<T> iterator();
// Returns an iterator (object) over elements of type T.
}
Documentation on
Iterable:
Recap: how to make our linked list
iterable
To implement the
Iterable<T>
interface, our
GenericLinkedList<T>
must defineall the methods in the
Iterable<T>
interface:
public class GenericLinkedList<T> implements SimpleList<T>, Iterable<T>
{
private class Node<T>
{
private T item;
private Node<T> next;
...
}
private Node<T> first; // Start of linked list
public GenericLinkedList()
{
first = null;
}
....
public Iterator<T> iterator() // Implements the Iterable<T> interface
{
// Returns an iterator (object) over elements of type T.
// We must define a class that returns an Iterator<T> object
}
}
Defining a class used to
create an
Iterator object
The Iterator<T> interface
of Java:
public interface Iterator<T>
{
public boolean hasNext();
// Returns true if the iteration has more elements.
public T next();
// Returns the next element in the iteration.
}
A class that can be
used to
create an
Iterator<T>
must implement the
interface,
e.g.:
public class MyLinkedListIterator<T> implements Iterator<T>
{
// *** what variables do we need to implement this object ? ***
public boolean hasNext()
{
// Returns true if the iteration has more elements.
}
public T next()
{
// Returns the next element in the iteration.
}
}
Iterating over a
linked list
Iterating over a
linked list is
visitingeverynode in the
linked list:
This is done
using the list traversal algorithm:
Node current = first;
while ( current != null ) // Find last list element
{
// Process current node here
current = current.next; // Move to next node
}
The
MyLinkedListIterator<T> class
must implement the
steps
of the list traversalalgorithm !!!
Defining a class used to
create an
Iterator object
Let's write the
MyLinkedListIterator<T> class:
(comment: we are
not making a linked list,
but an
iterator)
public class MyLinkedListIterator<T> implements Iterator<T>
{
// *** what variables do we need to implement this object ? ***
public MyLinkedListIterator(???) // Constructor (every class needs one)
{
// Initialize variables !
}
public boolean hasNext() // Returns true if there are more elements.
{
return current != null; // we aren't at the last node
}
public T next() // Returns the next element in the iteration.
{
if ( ! hasNext() )
throw new NoSuchElementException();
T res = current.item; // get item at current position
current = current.next; // move to the next node
return res;
}
}
Defining a class used to
create an
Iterator object
The Iterator object
must
remember the
current node in the
linked list: we use
current for this
purpose
public class MyLinkedListIterator<T> implements Iterator<T>
{
private Node <T> current; // Current position in the iteration
public MyLinkedListIterator(???) // Constructor (every class needs one)
{
// Initialize variables !
}
public boolean hasNext() // Returns true if there are more elements.
{
return current != null; // we aren't at the last node
}
public T next() // Returns the next element in the iteration.
{
if ( ! hasNext() )
throw new NoSuchElementException();
T res = current.item; // get item at current position
current = current.next; // move to the next node
return res;
}
}
Defining a class used to
create an
Iterator object
The constructor is used to
initiatescurrent
(we will passfirst to the
constructor):
public class MyLinkedListIterator<T> implements Iterator<T>
{
private Node <T> current; // Current position in the iteration
public MyLinkedListIterator(Node<T> f) // Constructor (every class needs one)
{
current = f; // Initialize
}
public boolean hasNext() // Returns true if there are more elements.
{
return current != null; // we aren't at the last node
}
public T next() // Returns the next element in the iteration.
{
if ( ! hasNext() )
throw new NoSuchElementException();
T res = current.item; // get item at current position
current = current.next; // move to the next node
return res;
}
}
Defining a class used to
create an
Iterator object
The hasNext() method
returns true if
current == null and
falseotherwise:
public class MyLinkedListIterator<T> implements Iterator<T>
{
private Node <T> current; // Current position in the iteration
public MyLinkedListIterator(Node<T> f) // Constructor (every class needs one)
{
current = f; // Initialize
}
public boolean hasNext() // Returns true if there are more elements.
{
return current != null; // True if there are unvisited nodes
}
public T next() // Returns the next element in the iteration.
{
if ( ! hasNext() )
throw new NoSuchElementException();
T res = current.item; // get item at current position
current = current.next; // move to the next node
return res;
}
}
Defining a class used to
create an
Iterator object
The next() method
returns the item
in the current node
and advance
the current pointer:
public class MyLinkedListIterator<T> implements Iterator<T>
{
private Node <T> current; // Current position in the iteration
public MyLinkedListIterator(Node<T> f) // Constructor (every class needs one)
{
current = f; // Initialize
}
public boolean hasNext() // Returns true if there are more elements.
{
return current != null; // True if there are unvisited nodes
}
public T next() // Returns the next element in the iteration.
{
if ( ! hasNext() )
throw new NoSuchElementException();
T res = current.item; // get item at current position
current = current.next; // move to the next node
return res;
}
}
Defining a class used to
create an
Iterator object
The next() methodmustthrow an
exception when
there are no more elements left:
(and we are
done)
public class MyLinkedListIterator<T> implements Iterator<T>
{
private Node <T> current; // Current position in the iteration
public MyLinkedListIterator(Node<T> f) // Constructor (every class needs one)
{
current = f; // Initialize
}
public boolean hasNext() // Returns true if there are more elements.
{
return current != null; // True if there are unvisited nodes
}
public T next() // Returns the next element in the iteration.
{
if ( ! hasNext() )
throw new NoSuchElementException();
T res = current.item; // get item at current position
current = current.next; // move to the next node
return res;
}
}
Recall: how to make our linked list
iterable
After
we have defined
a class to
make an Iterator<T> object,
we can nowfinish the
iterator() method:
public class GenericLinkedList<T> implements SimpleList<T>, Iterable<T>
{
private class Node<T>
{
private T item;
private Node<T> next;
...
}
private Node<T> first; // Start of linked list
public GenericLinkedList()
{
first = null;
}
....
public Iterator<T> iterator() // Implements the Iterable<T> interface
{
// ??? Returns an iterator (object) over elements of type T. Quiz// Use MyLinkedListIterator<T> to make an Iterator<T> object
}
}
Recall: how to make our linked list
iterable
The iterator() methodreturns a
MyLinkedListIterator<T> objectinitialized using
the first node of
the linked listfirst:
public class GenericLinkedList<T> implements SimpleList<T>, Iterable<T>
{
private class Node<T>
{
private T item;
private Node<T> next;
...
}
private Node<T> first; // Start of linked list
public GenericLinkedList()
{
first = null;
}
....
public Iterator<T> iterator() // Implements the Iterable<T> interface
{
return new MyLinkedListIterator<T>( first );
// Use MyLinkedListIterator<T> to make an Iterator<T> object
}
}
Organizing the
MyLinkedListIterator<T> class
Recall we
wrote the
Node<T> class
as an
inner class of the
GenericLinkedList<T> class:
public class GenericLinkedList<T> implements SimpleList<T>
{
/*******************************************************
The private inner class "Node"
*******************************************************/
private class Node<T>
{
private T item;
private Node<T> next;
public Node(T item, Node<T> next)
{
this.item = item;
this.next = next;
}
public String toString(){ return "" + this.item; }
} // End of private inner class "Node"
...
}
because
Node<T> will
only be used
by methodsinside the
GenericLinkedList<T> class
Organizing the
MyLinkedListIterator<T> class
Similarly, the
MyLinkedListIterator<T> class
will
only be used
by methodsinside the
GenericLinkedList<T> class, so we make it into an
inner classalso:
public class GenericLinkedList<T> implements SimpleList<T>, Iterable<T>
{
....
/*******************************************************
* Private inner (nested) class MyLinkedListIterator
* that implements the Java interface "Iterator"
********************************************************/
private class MyLinkedListIterator<T> implements Iterator<T>
{
private Node <T> current; // Current position in the iteration
public MyLinkedListIterator(Node<T> f) // Constructor (every class needs one)
{
current = f; // Initialize
}
public boolean hasNext() // Returns true if there are more elements.
{
return current != null; // True if there are unvisited nodes
}
public T next() // Returns the next element in the iteration.
{
if ( ! hasNext() )
throw new NoSuchElementException();
T res = current.item; // get item at current position
current = current.next; // move to the next node
return res;
}
}
}
The following test program shows that
we can now use our
GenericLinkedList<T> class
in a for-each-loop:
public static void main(String[] args)
{
System.out.println("Iterator");
GenericLinkedList<String> stringList =
new GenericLinkedList<String>();
stringList.addFirst("C");
stringList.addFirst("B");
stringList.addFirst("A");
System.out.println(stringList); // A -> B -> C
for ( String s : stringList )
System.out.println(s);
}