Iterator design pattern in Java

By | September 22, 2023

Iterator design pattern is a Behavioral design pattern that provides a way to access the elements of a collection without exposing the underlying implementation of the collection. In other words, it gives a way to traverse the elements of the collection without exposing the internal implementation of the collection.

Iterator design pattern in Java
Fig 1- Iterator design pattern

In the above figure, we can see we have a list of websites, and we can use any data structures (list, set, or map) to create and maintain a list of objects (here, website). Now, if the client or end-user wants to iterate over the list of objects, they should easily iterate without worrying about the underlying data structure or implementation used for maintaining the list of objects. In order to achieve this, the iterator design pattern gives an iterator to iterate over the collection of objects without exposing the internal implementation.

When to use Iterator design pattern?

Iterator design pattern are used when we want to provide a standard way to traverse the collection of objects without exposing the internal implementation or structure of the collection.

  • Collection framework in Java
  • Database Results: We can use iterator design pattern to traverse the result set of database query.
  • Menu System: In GUI-Applications, we can use iterator design pattern to implement menus. It can be stored in a collection and we can iterate over it to select the desired menu. For example: Music Playlist.

Example

To understand the Iterator design pattern, we create our own custom Iterator and use it to iterate (traverse) over the list of objects.

Steps to implement Iterator design pattern

Step 1- Create a Model class

First, we create a model class and name it Website. It will have two fields: name and URL.

Java
public class Website {
	
	private String name;
	private String url;
	
	public Website(String name, String url) {
		super();
		this.name = name;
		this.url = url;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getUrl() {
		return url;
	}
	public void setUrl(String url) {
		this.url = url;
	}
	
	@Override
	public String toString() {
		return "Website [name=" + name + ", url=" + url + "]";
	}
	
}

Step 2- Create a WebsiteManager class

After we have our model class, we create a WebsiteManager class, which can be used to add and get websites. Apart from this, we also created a method to get our custom iterator to traverse the website list.

Java
import java.util.ArrayList;
import java.util.List;

/**
 * 1. In WebsiteManager, we can add website to the list using 
 * 	  addWebsite() method. Also, get the website using getWebsite()
 * 	  method
 * 
 * 2. But, Iterator design patter says, the underlying implementation
 *    should not be know to the client. So, we need an iterator which
 *    iterates over the list and get all the websites without letting
 *    the implementation to the client--> For this, we define
 *    getCustomerIterator() method
 * 
 * @author paulsofts
 *
 */

public class WebsiteManager {

	List<Website> list = new ArrayList<>();
	
	public void addWebsite(Website website) {
		list.add(website);
	}
	
	public Website getWebsite(int index) {
		return list.get(index);
	}
	
	public CustomIterator getCustomIterator() {
		return new CustomIteratorImpl(list);
	}
}

Step 3- Create a custom Iterator

In this step, we will create a custom interface, CustomIterator. It will have 2 methods: hasNext() and next().

Java
/**
 * 1. hasNext(): check if the collection has next element
 * 				 or not, returns true if exist otherwise false
 * 
 * 2. next(): returns the next object or element from the collection
 * 
 * @author paulsofts
 *
 */
public interface CustomIterator {
	
	public boolean hasNext();
	
	public Object next();

}

Step 4- Implementation class for CustomIterator interface

Now, we create the implementation class for our custom interface.

Java
import java.util.ArrayList;
import java.util.List;

/**
 * 1. hasNext(): check if the collection has next element
 * 				 or not, returns true if exist otherwise false
 * 
 * 2. next(): returns the next object or element from the collection
 * 
 * @author paulsofts
 *
 */

public class CustomIteratorImpl implements CustomIterator {

	private List<Website> list = new ArrayList<>();
	private int index = 0;
	private int length;
	
	public CustomIteratorImpl(List<Website> list) {
		this.length = list.size();
		this.list = list;
	}
	
	@Override
	public boolean hasNext() {
		if(index >= length) {
			return false;
		}else {
			return true;
		}
	}

	@Override
	public Object next() {
		Object object = list.get(index);
		index += 1;
		return object;
	}

}

Step 5- Create Main class

Now, we create our main class, where we need our client code.

Java
/**
 * 1. We first create a list of website and different websites.
 * 
 * 2. We can see, the client will be unaware of the implementation
 * 	  for traverse of the list collection.
 * 
 * 3. The client can use the getcustomIterator to iterate over the list
 *    without worrying about the internal implementation.
 * 
 * @author paulsofts
 *
 */

public class Main {
	
	public static void main(String[] args) {
		
		WebsiteManager manager = new WebsiteManager();
		manager.addWebsite(new Website("Paulsofts", "paulsofts.com"));
		manager.addWebsite(new Website("JavaTPoint", "javatpoint.com"));
		manager.addWebsite(new Website("GeeksForGeeks", "geeksforgeeks.org"));
		
		CustomIterator iterator = manager.getCustomIterator();
		while(iterator.hasNext()) {
			System.out.println(iterator.next());
		}
		
	}

}

Output

Iterator design pattern in Java
Fig 2- Output

Leave a Reply

Your email address will not be published. Required fields are marked *