Iterator Design Pattern

Last Updated : 13 Feb, 2026

The Iterator design pattern is a behavioral design pattern that provides a way to access the elements of an aggregate object (like a list) sequentially without exposing its underlying representation. It defines a separate object, called an iterator, which encapsulates the details of traversing the elements of the aggregate, allowing the aggregate to change its internal structure without affecting the way its elements are accessed.

  • Iterator Pattern is a relatively simple and frequently used design pattern. There are a lot of data structures/collections available in every language.
  • Each collection must provide an iterator that lets it iterate through its objects. However, while doing so it should make sure that it does not expose its implementation.
iterator
Iterator Design pattern

Components

The Iterator design pattern consists of several components:

class_diagram_of_iterator_design_pattern_1
Class Diagram

1. Iterator Interface/Abstract Class: Defines the interface for accessing and traversing elements in the collection. It typically includes methods like hasNext(), next(), and optionally remove().

2. Concrete Iterator: Implements the Iterator interface and maintains the current position in the traversal of the aggregate. It provides the actual implementation for the traversal operations defined in the Iterator interface.

3. Aggregate Interface/Abstract Class: Defines the interface for creating an Iterator object. It typically includes a method like createIterator() that returns an Iterator object for the collection.

4. Concrete Aggregate: Implements the Aggregate interface and represents the collection of objects. It provides the implementation for creating an Iterator object that can traverse its elements.

Working

This pattern works by providing a separate object to traverse elements of a collection sequentially.

  • The collection provides an iterator object
  • The iterator keeps track of the current position
  • Methods like hasNext() and next() are used to move through elements
  • The internal structure of the collection remains hidden

Uses

The Iterator pattern is commonly used in the following scenarios.

  • Traversing lists, arrays, or collections
  • Accessing data structures without exposing their implementation
  • Implementing navigation features (next/previous)
  • Supporting multiple simultaneous traversals

Example

Problem Statement:

Let's say we have a collection of employees in a company, and we want to iterate over the employees to calculate their total salary. However, the employees are stored in different types of collections (arrays, lists, etc.), and we want to iterate over them without exposing the underlying collection types.

class_diagram_of_iterator_design_pattern
Class Diagram

Benefit of using the Iterator Pattern

The Iterator pattern allows us to access the elements of a collection sequentially without exposing its underlying representation. It provides a way to iterate over a collection regardless of its internal structure.

Implementation of above Example

Let’s break down into the component wise code:

1. Iterator Interface

Defines the methods for accessing and traversing the collection.

C++
template <typename T>\nclass Iterator {\npublic:\n    virtual bool hasNext() = 0;\n    virtual T next() = 0;\n};
Java
interface Iterator<T> {
    boolean hasNext();
    T next();
}
Python
from abc import ABC, abstractmethod\n\nclass Iterator(ABC):\n    @abstractmethod\n    def hasNext(self):\n        pass\n    @abstractmethod\n    def next(self):\n        pass
JavaScript
// JavaScript doesn't have interfaces, but we can mimic one using a class with abstract methods\nclass Iterator {
    hasNext() {
        throw new Error('Method hasNext() must be implemented.');
    }
    next() {
        throw new Error('Method next() must be implemented.');
    }
}

2. Aggregate Interface

Defines the method for creating an iterator.

C++
/*
Cpp implementation of Aggregate interface
*/
#include <vector>
#include <iterator>

template <typename T>
class Aggregate {
private:
    std::vector<T> collection;
public:
    Aggregate(std::vector<T> col) : collection(col) {}

    class Iterator {
    private:
        typename std::vector<T>::iterator position;
    public:
        Iterator(typename std::vector<T>::iterator pos) : position(pos) {}
        T operator*() { return *position; }
        Iterator& operator++() { ++position; return *this; }
        bool operator!=(const Iterator& other) const { return position!= other.position; }
    };

    Iterator createIterator() { return Iterator(collection.begin()); }
};
Java
interface Aggregate<T> {
    Iterator<T> createIterator();
}
Python
"""
Python implementation of Aggregate interface
"""
class Aggregate:\n    def __init__(self, collection):\n        self.collection = collection\n\n    class Iterator:\n        def __init__(self, collection):\n            self.collection = collection\n            self.position = 0\n\n        def __iter__(self):\n            return self\n\n        def __next__(self):\n            if self.position < len(self.collection):\n                result = self.collection[self.position]\n                self.position += 1\n                return result\n            else:\n                raise StopIteration\n\n    def create_iterator(self):\n        return self.Iterator(self.collection)
JavaScript
"""
JavaScript implementation of Aggregate interface
"""
class Aggregate {\n    constructor(collection) {\n        this.collection = collection;\n    }\n\n    createIterator() {\n        return new Iterator(this.collection);\n    }\n}\n\nclass Iterator {\n    constructor(collection) {\n        this.collection = collection;\n        this.position = 0;\n    }\n\n    next() {\n        if (this.position < this.collection.length) {\n            const result = this.collection[this.position];\n            this.position += 1;\n            return { value: result, done: false };\n        }\n        return { done: true };\n    }\n}\n

3. Concrete Iterator

Implements the Iterator interface and provides the actual iteration logic.

C++
#include <vector>
#include <stdexcept>

class Employee {
public:
    // Employee class definition
};

class EmployeeIterator {
private:
    int currentIndex = 0;
    std::vector<Employee> employees;

public:
    EmployeeIterator(std::vector<Employee> employees) : employees(employees) {}

    bool hasNext() {
        return currentIndex < employees.size();
    }

    Employee next() {
        if (!hasNext()) {
            throw std::out_of_range("No such element");
        }
        return employees[currentIndex++];
    }
};
Java
class EmployeeIterator implements Iterator<Employee> {
    private int currentIndex = 0;
    private List<Employee> employees;

    public EmployeeIterator(List<Employee> employees) {
        this.employees = employees;
    }

    @Override
    public boolean hasNext() {
        return currentIndex < employees.size();
    }

    @Override
    public Employee next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        return employees.get(currentIndex++);
    }
}
Python
class Employee:
    # Employee class definition
    pass

class EmployeeIterator:
    def __init__(self, employees):
        self.currentIndex = 0
        self.employees = employees

    def hasNext(self):
        return self.currentIndex < len(self.employees)

    def next(self):
        if not self.hasNext():
            raise StopIteration
        employee = self.employees[self.currentIndex]
        self.currentIndex += 1
        return employee
JavaScript
class Employee {
    // Employee class definition
}

class EmployeeIterator {
    constructor(employees) {
        this.currentIndex = 0;
        this.employees = employees;
    }

    hasNext() {
        return this.currentIndex < this.employees.length;
    }

    next() {
        if (!this.hasNext()) {
            throw new Error('No such element');
        }
        return this.employees[this.currentIndex++];
    }
}

4. Concrete Aggregate

Implements the Aggregate interface and provides the method to create an iterator for the collection.

C++
#include <vector>
#include <iterator>

class Employee; // Assume Employee class is defined elsewhere

class Company {
    std::vector<Employee> employees;

public:
    Company(std::vector<Employee> employees) : employees(employees) {}
    
    // Assuming Aggregate and Iterator are defined elsewhere
    class Iterator : public Iterator<Employee> {
        // Implementation of Iterator
    };

    Iterator createIterator() {
        return Iterator(employees);
    }
};
Java
class Company implements Aggregate<Employee> {
    private List<Employee> employees;

    public Company(List<Employee> employees) {
        this.employees = employees;
    }

    @Override
    public Iterator<Employee> createIterator() {
        return new EmployeeIterator(employees);
    }
}
Python
from typing import List, Iterator

# Assume Employee class is defined elsewhere

class EmployeeIterator:
    def __init__(self, employees: List['Employee']):
        self._employees = employees
        self._index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self._index < len(self._employees):
            employee = self._employees[self._index]
            self._index += 1
            return employee
        raise StopIteration

class Company:
    def __init__(self, employees: List['Employee']):
        self.employees = employees

    def create_iterator(self) -> 'EmployeeIterator':
        return EmployeeIterator(self.employees)
JavaScript
// Assume Employee class is defined elsewhere

class EmployeeIterator {
    constructor(employees) {
        this.employees = employees;
        this.index = 0;
    }

    [Symbol.iterator]() {
        return this;
    }

    next() {
        if (this.index < this.employees.length) {
            return { value: this.employees[this.index++], done: false };
        }
        return { done: true };
    }
}

class Company {
    constructor(employees) {
        this.employees = employees;
    }

    createIterator() {
        return new EmployeeIterator(this.employees);
    }
}

Complete code for the above example

This code demonstrates how the Iterator pattern can be used to iterate over a collection of employees in a company, regardless of the internal storage of the employees. Below is the complete code for the above example:

C++
#include <iostream>
#include <vector>

// Employee class
class Employee {
private:
    std::string name;
    double salary;

public:
    Employee(std::string name, double salary) : name(name), salary(salary) {}
    double getSalary() { return salary; }
};

// Iterator interface
template <typename T>
class Iterator {
public:
    virtual bool hasNext() = 0;
    virtual T next() = 0;
};

// Aggregate interface
template <typename T>
class Aggregate {
public:
    virtual Iterator<T>* createIterator() = 0;
};

// Concrete Iterator
class EmployeeIterator : public Iterator<Employee> {
private:
    int currentIndex = 0;
    std::vector<Employee> employees;

public:
    EmployeeIterator(std::vector<Employee> employees) : employees(employees) {}
    bool hasNext() override {
        return currentIndex < employees.size();
    }
    Employee next() override {
        if (!hasNext()) {
            throw std::out_of_range("No such element");
        }
        return employees[currentIndex++];
    }
};

// Concrete Aggregate
class Company : public Aggregate<Employee> {
private:
    std::vector<Employee> employees;

public:
    Company(std::vector<Employee> employees) : employees(employees) {}
    Iterator<Employee>* createIterator() override {
        return new EmployeeIterator(employees);
    }
};

// Main class
int main() {
    std::vector<Employee> employees = { Employee("Alice", 50000), Employee("Bob", 60000), Employee("Charlie", 70000) };
    Company company(employees);
    Iterator<Employee>* iterator = company.createIterator();

    double totalSalary = 0;
    while (iterator->hasNext()) {
        totalSalary += iterator->next().getSalary();
    }

    std::cout << "Total salary: " << totalSalary << std::endl;
    return 0;
}
Java
import java.util.*;

// Employee class
class Employee {
    private String name;
    private double salary;

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }
}

// Iterator interface
interface Iterator<T> {
    boolean hasNext();
    T next();
}

// Aggregate interface
interface Aggregate<T> {
    Iterator<T> createIterator();
}

// Concrete Iterator
class EmployeeIterator implements Iterator<Employee> {
    private int currentIndex = 0;
    private List<Employee> employees;

    public EmployeeIterator(List<Employee> employees) {
        this.employees = employees;
    }

    @Override
    public boolean hasNext() {
        return currentIndex < employees.size();
    }

    @Override
    public Employee next() {
        if (!hasNext()) {
            throw new NoSuchElementException();
        }
        return employees.get(currentIndex++);
    }
}

// Concrete Aggregate
class Company implements Aggregate<Employee> {
    private List<Employee> employees;

    public Company(List<Employee> employees) {
        this.employees = employees;
    }

    @Override
    public Iterator<Employee> createIterator() {
        return new EmployeeIterator(employees);
    }
}

// Main class
public class Main {
    public static void main(String[] args) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee("Alice", 50000));
        employees.add(new Employee("Bob", 60000));
        employees.add(new Employee("Charlie", 70000));

        Company company = new Company(employees);
        Iterator<Employee> iterator = company.createIterator();

        double totalSalary = 0;
        while (iterator.hasNext()) {
            totalSalary += iterator.next().getSalary();
        }

        System.out.println("Total salary: " + totalSalary);
    }
}
Python
# Employee class
class Employee:
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

    def get_salary(self):
        return self.salary

# Iterator interface
from abc import ABC, abstractmethod

class Iterator(ABC):
    @abstractmethod
    def has_next(self):
        pass

    @abstractmethod
    def next(self):
        pass

# Aggregate interface
class Aggregate(ABC):
    @abstractmethod
    def create_iterator(self):
        pass

# Concrete Iterator
class EmployeeIterator(Iterator):
    def __init__(self, employees):
        self.employees = employees
        self.index = 0

    def has_next(self):
        return self.index < len(self.employees)

    def next(self):
        if not self.has_next():
            raise StopIteration
        employee = self.employees[self.index]
        self.index += 1
        return employee

# Concrete Aggregate
class Company(Aggregate):
    def __init__(self, employees):
        self.employees = employees

    def create_iterator(self):
        return EmployeeIterator(self.employees)

# Main class
if __name__ == "__main__":
    employees = [Employee("Alice", 50000), Employee("Bob", 60000), Employee("Charlie", 70000)]
    company = Company(employees)
    iterator = company.create_iterator()

    total_salary = 0
    while iterator.has_next():
        total_salary += iterator.next().get_salary()

    print(f'Total salary: {total_salary}')
JavaScript
class Employee {
    constructor(name, salary) {
        this.name = name;
        this.salary = salary;
    }
}
// Iterator interface
class Iterator {
    constructor(collection) {
        this.collection = collection;
        this.currentIndex = 0;
    }
    hasNext() {
        return this.currentIndex < this.collection.length;
    }
    next() {
        if (!this.hasNext()) {
            throw new Error('No such element');
        }
        return this.collection[this.currentIndex++];
    }
}
// Aggregate interface
class Aggregate {
    createIterator() {
        return null;
    }
}
// Concrete Iterator
class EmployeeIterator extends Iterator {
    constructor(collection) {
        super(collection);
    }
}
// Concrete Aggregate
class Company extends Aggregate {
    constructor(collection) {
        super();
        this.collection = collection;
    }
    createIterator() {
        return new EmployeeIterator(this.collection);
    }
}
// Main function
function main() {
    const employees = [
        new Employee("Alice", 50000),
        new Employee("Bob", 60000),
        new Employee("Charlie", 70000)
    ];
    const company = new Company(employees);
    const iterator = company.createIterator();
    let totalSalary = 0;
    while (iterator.hasNext()) {
        totalSalary += iterator.next().salary;
    }
    console.log("Total salary: " + totalSalary);
}
main();

Output
Total salary: 180000.0

Real-Life Example

TV Remote Channel List:
When you press next or previous on a remote, you don’t know how channels are stored internally—you just iterate through them one by one.

Advantages

This pattern simplifies traversal of collections without exposing their internal structure.

  • Provides a uniform way to access elements of a collection
  • Hides the internal representation of the collection
  • Supports multiple traversals at the same time

Disadvantages

Despite its usefulness, it has some drawbacks.

  • Can increase the number of classes
  • May add extra overhead for simple collections
  • Can be unnecessary for languages with built-in iterators
Comment

Explore