What is Iterator Pattern?
Iterator pattern is a behavioral pattern that provides a way to access the elements of an aggregate (collection) object sequentially without exposing its underlying representation.
When to use it?
- Use Iterator pattern when you don't want to expose the data structure of your collection.
- User Iterator pattern when you want one common interface to traverse different data structures instead of having many similar traversal codes for each data structure in your app.
Problem
Company "Alpha Inc." is going to merge with "Beta Inc.". We are in HR department and have to merge their employees data together.
EmployeeListA holds Alpha employees' data, and EmployeeListB has Beta employees' data. Because EmployeeListA uses Array data structure and EmployeeListB uses ArrayList, we write two traversal codes.
public class HRDepartment {
public void printEmployee(){
EmployeeListA employeeListA = new EmployeeListA("Alpha Inc");
String[] alphaEmployee = employeeListA.getEmployees();
EmployeeListB employeeListB = new EmployeeListB("Beta Inc");
List<String> betaEmployee = employeeListB.getEmployees();
// Traversal code for Array
for (int i = 0; i < alphaEmployee.length; i++) {
System.out.println(alphaEmployee[i] + " from Alpha Inc.");
}
// Traversal code for ArrayList
for (int i = 0; i < betaEmployee.size(); i++) {
System.out.println(betaEmployee.get(i) + " from Beta Inc.");
}
}
}
Can you spot the problems? Here's the issue our code currently has:
- We are coding to concrete implementation (
EmployeeListAandEmployeeListB) not to an interface. - If we decide to switch
EmployeeListAdata structure from Array to another one such as hash map, we need to modify ourHRDepartmentclass a lot. -
HRDepartmentneeds to know aggregate's internal structure, in other words, we are exposing our collection's data structure. - We have duplication of traversal code for different data structure, Array and ArrayList.
Solution
Encapsulate iteration logic
So where to begin? Let's remove our duplicate iteration codes.
It would be great if we can encapsulate iteration logic and introduce a common interface so that HRDepartment can use just one interface to iterate any data structure.
We need Iterator interface to decouple iteration logic from HRDepartment.
public interface Iterator {
boolean hasNext();
String next();
}
hasNext() returns boolean value indicating whether a collection has next element or not. next() returns next element in a collection. (you will see actual implementation later)
In EmployeeListA/EmployeeListA, We removed getEmployees() method because it exposes our aggregate's data structure. And importantly, we wrote new method createIterator() which creates an corresponding concrete Iterator, for example, EmployeeListA.createIterator() instantiates EmployeeListAIterator.
Introduce common interface for aggregates
Okay, we now encapsulated Iteration logic, our aggregates do not expose their underlying representation, removed duplicate traversal codes. But still one problem remains, HRDepartment depends on concrete aggregates. Let's introduce a common interface for concrete aggregates.
Structure
Implementation in Java
I'll omit EmployeeListBIterator and EmployeeListB's implementation as they are similar to those of EmployeeListAIterator and EmployeeListA. If you're not sure how to implement them, you can check in my GitHub repo (link to my repo is at the end of this blog).
public interface Iterator {
boolean hasNext();
String next();
}
public class EmployeeListAIterator implements Iterator {
private String[] employees;
private int index = 0;
public EmployeeListAIterator(String[] employees) {
this.employees = employees;
}
@Override
public boolean hasNext() {
if (index >= employees.length || employees[index] == null) {
return false;
}
return true;
}
@Override
public String next() {
String employee = employees[index];
index++;
return employee;
}
}
public interface EmployeeList {
Iterator createIterator();
String getCompanyName();
}
public class EmployeeListA implements EmployeeList{
private String companyName;
private String[] employees;
private int SIZE = 5;
private int index = 0;
public EmployeeListA(String companyName) {
this.companyName = companyName;
employees = new String[SIZE];
addEmployee("Alice");
addEmployee("Alisha");
addEmployee("Alex");
}
public void addEmployee(String name) {
employees[index] = name;
index++;
}
public Iterator createIterator() {
return new EmployeeListAIterator(employees);
}
public String getCompanyName() {
return companyName;
}
}
public class HRDepartment {
EmployeeList listA;
EmployeeList listB;
public HRDepartment(EmployeeList listA, EmployeeList listB) {
this.listA = listA;
this.listB = listB;
}
public void printEmployee() {
Iterator listAIterator = listA.createIterator();
Iterator listBIterator = listB.createIterator();
System.out.println("--- Employees from " + listA.getCompanyName() + " ---");
printEmployee(listAIterator);
System.out.println("--- Employees from " + listB.getCompanyName() + " ---");
printEmployee(listBIterator);
}
private void printEmployee(Iterator iterator) {
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
Output:
--- Employees from Alpha Inc ---
Alice
Alisha
Alex
--- Employees from Beta Inc ---
Bob
Bella
Benjamin
Pitfalls
- Iterator itself imply no ordering in which elements are visited during iteration. The order of iteration depends on the underlying data structure being traversed, not on the Iterator.
- Iterator does not support accessing elements by index.
Iterator & Iterable interface in Java
Before the end of this blog, let's check how we can use java.util.Iterator.
All Collection classes such as ArrayList, implement the Collection interface, which extends Iterable interface. Thus every Collection class is Iterable.
public class IteratorDemo {
public static void main(String[] args) {
List<Integer> nums = new ArrayList<>(List.of(0, 1, 2, 3));
Iterator<Integer> iterator = nums.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
You can check all the design pattern implementations here.
GitHub Repository





Top comments (0)