CompSci-61B Lecture Topic 3
Iterators

Instructor: Prof. Robert Burns

Ref: Carrano ch.8 and App.B

Traversing An List With Iteration
the "for-each" loop structure (and more...)
alternative to for-loop with "getEntry" action
also applies to non-indexed data structures (later)

IterableList<Integer> a;
a = new IterableArrayList<Integer>();
...
for (int i = 0; i < a.size(); i++)
  System.out.print(a.getEntry(i));
...
for (Integer value: a)   <- "for-each"
  System.out.print(value);

An Iterating Object
interface "Iterator" in package "java.util"
an accessor method of the data structure class
  creates and returns an iterating object
object's methods: next() and hasNext()
  but not directly used in for-eash

Supporting Iteration In A Class
include accessor to create/return iterating object
to support for-each, accessor must be:
  public Iterator<T> iterator()
  and implement the "Iterable" interface
otherwise, use an iterating for-loop

for (Iterator it = a.getAnIterator(); it.hasNext();)
  System.out.print(a.next());
Be sure to import "java.util.Iterator"

The Approach
encapsulate an inner class for the iterator object
include "iterator" accessor to
  create/return an iterator object

1. implement the "Iterable" interface for class
2. write inner class that implements "Iterator"
  with hasNext(), next() and remove()
3. write public Iterator<T> iterator()

The Concept of Inheritance
creating a new class as extension of existing class
  "is-a" vs. "has-a"
adding iteration support to the List interface
  without modifying original class
  without copy/pasting its code
implemented via the extends keyword (e.g.:)
public interface IterableList<T> extends List<T>
  then just add the new actions!
extend "java.util.Iterable" too, to enable for-each
public interface IterableList<T> extends List<T>, Iterable<T>
directly accessing private members: protected -- later

Incomplete Implementation
throwing "exceptions"

public void remove() // for "java.util.Iterator"
{
  throw new UnsupportedOperationException("...");
}
Implementing Iteration
include a private inner class extending "java.util.Iterator"
private class MyIterator implements Iterator<T>
{
  private... // to track position

  public boolean hasNext()
  {
    false if final position already past
  }

  public T next()
  {
    if (hasNext())
    {
      get reference to value at current position
      increment current position
      return reference
    }
    else
      throw new NoSuchElementException...
  }

  public void remove()
  {
    throw new UnsupportedOperationException...
  }
}
...and an accessor to create/return a MyIterator object
public Iterator<T> iterator() // an accessor
{
  return new MyIterator();
}
Adding Iteration To "MyArrayList"
create new class "MyIterableArrayList<T>"
extend "MyArrayList<T>" -- using inheritance
implement "Iterable<T>"
add private class "MyIterator"
  using accessors to get private data
add accessor public Iterator<T> iterator()

Adding Iteration To "MyLinkedList"
create new class "MyIterableLinkedList<T>"
new version of "MyLinkedList<T>" -- not using inheritance
add "tail" reference and "prev" link: doubly-linked list
improved private Node getNodeAt
  add currentNode and currentIndex
  use for faster access to indexed node...
  ...with possible search scenarios
implement "Iterable<T>"
add private class "MyIterator"
add accessor public Iterator<T> iterator()


For Array-based Structures
  private class MyIterator implements Iterator<T>
  {
    private int index; // to track position

    public boolean hasNext()
    {
      return index < MyIterableArrayList.this.size();
    }

    public T next()
    {
      if (hasNext())
        return MyIterableArrayList.this.getEntry(index++);
      else
        throw new NoSuchElementException("illegal call to " + getClass().getName() + ".MyIterator.next");
    }

    public void remove()
    {
      throw new UnsupportedOperationException(getClass().getName() + ".MyIterator.remove is not supported");
    }
  }

  public Iterator<T> iterator()
  {
    return new MyIterator();
  }

For Linked-list Structures
  private class MyIterator implements Iterator<T>
  {
    private Node p; // to track position

    private MyIterator()
    {
      p = head;
    }

    public boolean hasNext()
    {
      return p != null;
    }

    public T next()
    {
      if (hasNext())
      {
        T value = p.value;
        p = p.next;
        return value;
      }
      else
        throw new NoSuchElementException("illegal call to " + getClass().getName() + ".MyIterator.next");
    }

    public void remove()
    {
      throw new UnsupportedOperationException(getClass().getName() + ".MyIterator.remove is not supported");
    }
  }

  public Iterator<T> iterator()
  {
    return new MyIterator();
  }

Doubly-linked List Node Insertion of a value at index:
      Node prev = ... // insert after this node, null if index=0 or list is empty
      Node p = ... // insert before this node node, null if empty list or adding to end

      // create new node at current position
      currentNode = ...
      currentNode.value = ...
      currentNode.next = p; // possibly null
      currentNode.prev = prev; // possibly null
      currentIndex = index;
    
      // manage the "next" link and "head"
      if (prev == null)
        head = currentNode;
      else
        prev.next = currentNode;

      // manage the "prev" link and "tail"
      if (p == null)
        tail = currentNode;
      else 
        p.prev = currentNode;

Doubly-linked List Node Removal at index:
      Node prev = ... // the node before the node to be removed, null if index=0
      Node p = ... // the node after the node to be removed, null if removing to end

      // manage the "next" link and "head"
      if (prev == null)
        head = p;
      else
        prev.next = p;

      // manage the "prev" link and "tail"
      if (p == null)
        tail = prev;
      else
        p.prev = prev;

      // reset current position because currentNode is going away
      if (p == null) // move towards head if tail got removed
      {
        currentNode = prev; // possibly null if only remaining node got removed
        --currentIndex; // possibly -1 (but ignored because currentNode is null)
      }
      else 
        currentNode = p; // currentIndex is unchanged

[ Home | Contact Prof. Burns ]