Sunday 13 December 2015

Iterator Pattern in Java | Simple Genric implementation

Hello Friends,

Today I wish to share with you the Iterator pattern. It is very powerful way to iterate over any collection. It is fast and also helpful in hiding the complicated way to traverse the underlying data structure of the collection.

Suppose we have a Collection of String Objects stored in a class. Today I hold the items in simple array, tomorrow I may choose to use LinkedList to hold the items, and may be later I decide to use Tree or any other efficient data structure to hold my data. I want the users of my collection class not to get troubled by my decision of changing the underlying data structure. I want to provide them a uniform way to access the items in the collection.

The Iterator pattern solves this problem nicely. I can provide an Iterator to my collection and it can be used by the users of my collection class to iterate over the items in the collection. The internal traversing can be handled internally in the Iterator class but the iteration methods contract never changes. Lets see below as how we can implement this.

An interface iterator can be defined with hasNext() returning boolean [ true if collection has more items to iterate, else false ], and next() to get the next item in the collection. Collection class has a private concrete class implementing the Iterator and the object of concrete class(implementing the Iterator) can be exposed using a public method.


Suppose we have a collection class named Lib.java It can hold items and I want a uniform way using which outside world (LibManager.java) can iterate my collection class.

Lets see the UML class diagram for this.



To keep the implementation simple, I have just kept add method in ICollection. Also the exceptional conditions such as array index out of bounds are not handled. We can do all that once we get the understanding of the Iterator pattern.
Actual java.util classes Like ArrayList, LinkedList etc uses this pattern. They implement java.util.Iterable and hence enhanced for loop ( for each loop ) can be used with them.
Enhanced for loop uses iterator to iterate and hence is faster. Usually in our code we get List of object, List can be actually be implemented by LinekdList or ArrayList but using Iterator to iterate is always faster as to iterate any element using Iterator  only one step ahead needs to be taken whereas in case of traditional for loop, if the concrete implementation is LinekedList then again and again items will be traversed starting from the start of the linkedList.
The Underlying data structure can change anytime, (say from ArrayList to LinekdList) hence using Iterator ( or enhanced for loop ) to iterate is always preferable.



public interface ICollection<E> {
	public void add(E element);
}
 
public interface SIterable<P> {
	public CIterator<P> iterator();
}
 
public interface CIterator<L> {
	public boolean hasNext();

	public L next();
}
 
public class Lib<T> implements SIterable<T>,ICollection<T>{
	private Object[] items;
	private int maxSize;
	private int size;
	public Lib(int size){
		maxSize = size;
		items = new Object[maxSize];
	}
	@Override
	public void add(T element) {
		items[size++] = element;
	}
	
	@Override
	public CIterator<T> iterator() {
		return new LibIterator();
	}
	
	private class LibIterator implements CIterator<T>{
		int iteratingIndex = 0;
		@Override
		public boolean hasNext() {
			return iteratingIndex < size;
		}

		@Override
		public T next() {
			Object nextItem = items[iteratingIndex];
			iteratingIndex++;
			return ((T)nextItem);
		}
		
	}
}
 
public class LibManager {
	public static void main(String[] args) {
		Lib<String> lib = new Lib<String>(5);
		lib.add("Bread");
		lib.add("Butter");
		lib.add("Apple");
		lib.add("Orange");
		lib.add("Pineapple");
		CIterator<String> itr = lib.iterator();
		while(itr.hasNext()){
			System.out.println(itr.next());
		}
	}
}