Iterator Design Pattern in Java

This article explains Iterator design pattern in java with UML class diagram. It then takes an example scenario in java and explains it with class diagram and code.

Introduction: Iterator Design Pattern is a behavioral design pattern among the Gang Of Four(GOF) Design PatternsArticle on GOF Patterns & their types. Being a behavioral design pattern, the Iterator pattern deals with how objects of the designed system interact with each other.

What is Iterator Design Pattern: Iterator design pattern implements the logic for sequential access of a collection of data outside of the collection(aka an aggregate) itself. This decouples the iteration logic from the collection implementation.

Defining an abstract interface for an iterator makes it possible to have multiple ways of iterating the same collection. Lets say we have a collection representing a binary tree. We can then have multiple concrete implementations of the same iterator abstraction accessing the elements in the tree using different traversal logic like in-order,pre-order and post-order. The binary tree collection remains the same but using Iterator pattern we access it in multiple ways without altering and/or directly accessing the binary tree implementation itself.

Scenarios in which Iterator Design Pattern can be used: Given below are the scenarios in which an iterator pattern implementation is ideal for accessing elements of a collection-

  1. Collection’s internal implementation is to be hidden: When the collection to be iterated does not want to expose its internal structure/representation to all the accessors of its data. The knowledge of internal structure of the collection is then restricted to the iterator. The accessors directly do not access the collection.
  2. Multiple ways of traversing the collection are possible: As explained with the binary tree example above, multiple implementations of the iterator abstraction enable the accessors to traverse the collection in multiple ways.
  3. Iteration logic is decoupled from the collection’s internal structure: This scenario refers to polymorphic iteration. Lets say the collection being accessed itself has an abstract interface which multiple types of collection implementations possible.
    For our binary tree example lets say we have two variations of binary trees – balanced and AVL. We define a common interface named BinaryTree and then define two concrete implementations of BinaryTree named – BalancedBinaryTree & AVLBinaryTree. The iterator abstraction would then use the interface BinaryTree to access the concrete binary tree collection implementation which could be any of the two types. This is an example of polymorphic iteration.

Class Diagram for Iterator Design Pattern

Iterator Design Pattern Class Diagram

Explanation of Iterator Design Pattern’s Class Diagram

  • Aggregate is the base interface for the family of collections which are to be iterated.It defines the method createIterator() in which all aggregates instantiate and return their own iterators.
  • ConcreteAggregate is the concrete subclass of aggregate. It overrides createIterator().
  • Iterator is the base interface for the family of iterators which traverse over the Aggregate family of collections.
  • Iterator has four methods –
    • firstItem() resets the iterator to point to the first item in the collection.
    • nextItem() moves the iterator forward to next item in the collection.
    • isOver() returns a boolean indicating whether the collection is fully traversed or not.
    • getCurrentItem() returns the item to which the iterator is currently pointing.
  • ConcreteIterator is a concrete instance of Iterator interface. It stores internally the concrete aggregate’s instance over which it has to iterate. This concrete aggregate instance is returned to it by the concrete aggregate itself.

Iterator Design Pattern Example Implementation in Java-Class Diagram

Iterator Design Pattern in Java Class Diagram

Code for the classes shown in Java Example’s Class Diagram

Interface Sequence<T>
public interface Sequence<T> {
 public SequenceIterator<T> createSeqIterator();
}
Interface SequenceIterator<T>
public interface SequenceIterator<T> {
 public T getCurrentItem();
 public boolean isOver();
 public void nextItem();
 public void firstItem();
}
Class ListSequence<T>
import java.util.ArrayList;
import java.util.List;
public class ListSequence<T> implements Sequence<T> {
 private List<T> list=new ArrayList<T>();
 @Override
 public SequenceIterator<T> createSeqIterator() {
  return new ListSequenceIterator<T>(this);
 }
 //setter & getter for private list variable
}
Class LinkedListSequence<T>
import java.util.ArrayList;
import java.util.List;
public class LinkedListSequence<T> implements Sequence<T> {
 private List<T> list=new ArrayList<T>();
 @Override
 public LinkedListSequenceIterator<T> createSeqIterator() {
  return new LinkedListSequenceIterator<T>(this);
 }
 //setter & getter for private list variable
}
class ListSequenceIterator<T>
public class ListSequenceIterator<T> implements SequenceIterator<T>{
 private ListSequence<T> list=null;
 public ListSequenceIterator(ListSequence<T> list) {
  super();
  this.list = list;
 }
 private int currentItemNo=0;
 @Override
 public T getCurrentItem() {
  return (this.list.getList().get(currentItemNo));
 }
 @Override
 public boolean isOver() {
  if(currentItemNo==list.getList().size()){
   return true;
  }else{
   return false;
  }
 }
 @Override
 public void nextItem() {
  this.currentItemNo++;
 }
 @Override
 public void firstItem() {
  this.currentItemNo=0;
 }
}
Class LinkedListSequenceIterator<T>
public class LinkedListSequenceIterator<T> implements SequenceIterator<T>{
 private LinkedListSequence<T> list=null;
 public LinkedListSequenceIterator(LinkedListSequence<T> list) {
  super();
  this.list = list;
 }
 private int currentItemNo=0;
 //Rest of the code for this class is same as ListSequenceIterator
 //as LinkedList & ArrayList both implement java.util.List
}
Client.java with the main() method
import java.util.Arrays;
public <span class="jb-highlight-lightgreen">class Client</span> {
 public static void main(String[] args) {
  //Iterating over a list sequence
  ListSequence<Integer> listSequence = new ListSequence<Integer>();
  listSequence.setList(Arrays.asList(12,20,28,36));
  ListSequenceIterator<Integer> listSeqIterator=  (ListSequenceIterator<Integer>)listSequence.createSeqIterator();
  System.out.println("Printing listSequence's items");
  printIteratorElements(listSeqIterator);
  //Iterating over a list sequence
  LinkedListSequence<Integer> linkedListSequence = new LinkedListSequence<Integer>();
  linkedListSequence.setList(Arrays.asList(111,122,108,242));
  LinkedListSequenceIterator<Integer> linkedListSeqIterator=(LinkedListSequenceIterator<Integer>)linkedListSequence.createSeqIterator();
  System.out.println("Printing linkedListSequence's items");
  printIteratorElements(linkedListSeqIterator);
 }
 private static void printIteratorElements(SequenceIterator<?> listSeqIterator){
  while(listSeqIterator.isOver()==false){
   System.out.println("item->"+listSeqIterator.getCurrentItem());
   listSeqIterator.nextItem();
  }
 }
}
 OUTPUT of the above code
Printing listSequence’s items
item->12
item->20
item->28
item->36
Printing linkedListSequence’s items
item->111
item->122
item->108
item->242
Explanation of Java Example’s Class Diagram & Code
The Java class diagram above depicts Iterator Design pattern implemented for traversing a Sequence interface which has two concrete classes – ListSequence & LinkedListSequence. Lets quickly go through whats there in Java’s example’s class diagram & corresponding code –

  • Sequence is the base interface for a collection-type of data structure. ListSequence & LinkedListSequence are concrete implementations of Sequence. They hold their data in instance of java.util.ArrayList and java.util.LinkedList respectively.
  • SequenceIterator is the base interface for family of iterators capable of traversing Sequences. ListSequenceIterator & LinkedListSequenceIterator are concrete subclasses of SequenceIterator responsible for iterating over ListSequence & LinkedListSequence respectively.
  • Client creates an instance of ListSequence, initializes it with an ArrayList with few values. Client then creates an instance of ListIterator from it. Similary, Client creates instances of LinkedListSequence, populates it with a LinkedList instance & creates an instance of LinkedListIterator.
  • Client uses a generic method called printIteratorElements() which takes as input param all SequenceIterators and prints their contents.

Summary: In the above tutorial we understood what is Iterator design pattern and the main scenarios in which it is applicable. We then looked at the UML class diagram for Iterator Design Pattern & its explanation, a Java Use Case implementing Iterator pattern with its class diagram and code for the classes shown in the class diagram, followed by explanation of both the class diagram & code. This concludes the tutorial on Iterator design pattern.

 

Digiprove sealCopyright © 2014-2017 JavaBrahman.com, all rights reserved.