Iterator Design Pattern Example in Java

The Iterator design pattern provides a way to access the elements of an aggregate object (such as a collection) sequentially without exposing its underlying representation. The pattern decouples the collection from the code that uses it, making it easy to change the collection implementation without affecting the client code.

A real-world example of the Iterator pattern in Java can be seen in the Java Collection Framework.

Table of Content :

The Collection Framework provides a set of interfaces and classes for working with collections of objects, such as lists, sets, and maps. These collections are implemented using different data structures, such as arrays, linked lists, and hash tables.

To iterate over the elements of a collection, the Collection Framework provides an Iterator interface and its concrete implementations, such as ArrayList and HashSet. The Iterator interface defines the methods for iterating over the elements of a collection, including hasNext() and next(). The concrete implementations provide the actual implementation for these methods based on the data structure used.

package com.javacodestuffs.core.java.iterator.pattern; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; public class ListIteratorExample { public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("Bala"); names.add("Anna"); names.add("Charlie"); names.add("Joseph"); names.add("Sara"); names.add("Shivani"); ListIterator<String> iterator = names.listIterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } }

output:

Bala Anna Charlie Joseph Sara Shivani

Iterator pattern Design participants

The Iterator pattern consists of four Design participants:

  • Iterator interface: defines the methods for accessing the elements of the collection.
  • Concrete Iterator: implements the Iterator interface and provides the implementation for the methods.
  • Aggregate interface: defines the methods for creating an Iterator object.
  • Concrete Aggregate: implements the Aggregate interface and provides the implementation for the Iterator creation method.

Iterator design pattern example

Here's an example implementation of the Iterator design pattern in Java:

Iterator interface

package com.javacodestuffs.core.java.iterator.pattern; public interface Iterator<T> { boolean hasNext(); T next(); }

Concrete Iterator

package com.javacodestuffs.core.java.iterator.pattern; import java.util.NoSuchElementException; public class ArrayIterator<T> implements Iterator<T> { private final T[] array; private int index; public ArrayIterator(T[] array) { this.array = array; this.index = 0; } @Override public boolean hasNext() { return index < array.length; } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } return array[index++]; } }

Aggregate interface

package com.javacodestuffs.core.java.iterator.pattern; public interface Aggregate<T> { Iterator<T> createIterator(); }

Concrete Aggregate

package com.javacodestuffs.core.java.iterator.pattern; public class ArrayCollection<T> implements Aggregate<T> { private final T[] array; public ArrayCollection(T[] array) { this.array = array; } @Override public Iterator<T>createIterator() { return new ArrayIterator<>(array); } }

IteratorClient

package com.javacodestuffs.core.java.iterator.pattern; public class IteratorClient { public static void main(String[] args) { System.out.println("----------- Interator for Strings -----------"); String[] names = { "Anna", "Bala", "Sara", "Joseph", "Shivani" }; ArrayCollection<String> collection = new ArrayCollection<>(names); Iterator<String> iterator = collection.createIterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } Integer[] intList = { 101, 105, 50, 1001, 25 }; System.out.println("-----------Interator for Integer-----------"); ArrayCollection&Integer> intCollection = new ArrayCollection<>(intList); Iterator&Integer> intIterator = intCollection.createIterator(); while (intIterator.hasNext()) { System.out.println(intIterator.next()); } } }

In this implementation, the Iterator interface defines the hasNext and next methods for accessing the elements of the collection. The ArrayIterator class is the concrete iterator, which implements the Iterator interface and provides the implementation for the methods.

The Aggregate interface defines the createIterator method for creating an Iterator object.

The ArrayCollection class is the concrete aggregate, which implements the Aggregate interface and provides the implementation for the createIterator method.

The IteratorClient code creates an instance of the ArrayCollection, gets an Iterator object using the createIterator method, and then iterates over the elements using the hasNext and next methods of the Iterator.

Iterator design pattern advantages

The Iterator design pattern offers several advantages, including:

  • Encapsulating the collection : The Iterator design pattern encapsulates the collection's implementation details and provides a standard interface for iterating over its elements. This allows the collection to change its implementation without affecting the client code.
  • Simplicity: The pattern simplifies the code by separating the iteration logic from the collection. It also eliminates the need for boilerplate code to iterate over collections.
  • Flexibility: The pattern allows multiple iterations to be in progress at the same time without interfering with each other. It also allows the elements to be accessed in different orders, such as reverse or random order.
  • Efficiency: The pattern enables lazy iteration, where the elements are retrieved only when requested, rather than all at once. This improves the efficiency of the application and reduces memory usage.
  • Compatibility: The Iterator design pattern is compatible with other design patterns, such as the Composite and Factory Method patterns. It can also be used with different types of collections, such as arrays, lists, and sets.

Overall, the Iterator design pattern promotes code reuse, improves code maintainability, and enhances the performance of the application by providing an efficient way to iterate over collections.

Conclusion

In this article we have seen Iterator Design Pattern . We also seen how to use Factory Design Pattern in java with examples.
All the classes code is available on GitHub.