Friday, 30 August 2013

Iterator Design Pattern - Implementation

🚀 Master Java Design Patterns & Software Architecture!

Subscribe to Ram N Java for clean software architecture patterns, design pattern deep dives, and production-ready implementation guides!

🔔 Subscribe to Ram N Java

Implementing the Iterator Design Pattern in Java

The Iterator Design Pattern is one of the most widely used behavioral patterns in software engineering. While the concept of stepping through elements sequentially is straightforward, creating a robust, reusable implementation requires adhering to sound design principles. Implementing the pattern correctly ensures that custom aggregate structures—such as trees, custom lists, or graph nodes—can be traversed predictably without exposing internal data structures or creating concurrent modification bugs.

Key Components & Architecture

  • The Iterator Interface: Declares core traversal operations such as hasNext(), next(), and optionally remove().
  • The Concrete Iterator: Implements the interface, maintains the internal cursor position, and directly queries the collection to retrieve items in sequential order.
  • The Aggregate / Container Interface: Defines factory methods (e.g., createIterator() or Java's iterator() via Iterable<T>) to decouple the creation of iterators from client code.
  • The Concrete Aggregate: Manages internal data storage and instantiates the concrete iterator with a reference to itself.

Implementation Best Practices

  1. Implement Standard Interfaces: Leverage Java's built-in Iterable<T> and Iterator<T> interfaces so your custom collections seamlessly integrate with enhanced for-each loops and Stream APIs.
  2. Guard Against Fail-Fast Scenarios: Track structural modifications (like a modCount variable) to detect concurrent modifications and immediately throw ConcurrentModificationException if the collection is altered outside the iterator.
  3. Encapsulate Concrete Iterators: Declare concrete iterators as private inner or package-private classes within the aggregate to protect internal structural references from external tampering.
  4. Handle Boundaries Gracefully: Ensure next() throws NoSuchElementException when called without checking hasNext(), avoiding silent failures or null pointer exceptions.

Why Proper Implementation Matters

  • Polymorphic Iteration: Clients can write uniform traversal algorithms that work identically across arrays, trees, linked nodes, or custom data structures.
  • Concurrent Traversals: Multiple clients can simultaneously iterate over the same aggregate without race conditions, since each iterator holds its own independent cursor.
  • Clean Separation of Concerns: The aggregate class stays focused strictly on data storage, while traversal mechanics remain isolated in dedicated iterator objects.

Recommended Next Videos

Continue your deep dive into behavioral patterns and collection traversal with these related guides from our channel:


Click here to watch in Youtube : https://www.youtube.com/watch?v=uRiKSJAnmeA

Click the below Image to Enlarge
Iterator Design Pattern - Implementation

















IteratorPatternDemo.Java

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class IteratorPatternDemo
{

public static void main( String[] args )
{
ArrayList<String> listOfCountries = new ArrayList<String>();
listOfCountries.add("India");
listOfCountries.add("US");
listOfCountries.add("Japan");
listOfCountries.add("France");

Iterator<String> iterator = listOfCountries.iterator();
System.out.println("Iterator type for the Datastructure ArrayList : "+iterator.toString());
System.out.println();
while( iterator.hasNext() )
{
String countryName = iterator.next();
System.out.println("Country Name : " + countryName);
}
System.out.println();
Set<String> setOfCountries = new HashSet<String>();
setOfCountries.add("India");
setOfCountries.add("US");
setOfCountries.add("Japan");
setOfCountries.add("France");
Iterator<String> iterator1 = setOfCountries.iterator();
System.out.println("Iterator type for the Datastructure HashSet : "+iterator1.toString());
System.out.println();
while( iterator1.hasNext() )
{
String countryName = iterator1.next();
System.out.println("Country Name : " + countryName);
}

}

}

Output

Iterator type for the Datastructure ArrayList : java.util.AbstractList$Itr@12dacd1

Country Name : India
Country Name : US
Country Name : Japan
Country Name : France

Iterator type for the Datastructure HashSet : java.util.HashMap$KeyIterator@30c221

Country Name : France
Country Name : US
Country Name : Japan
Country Name : India

No comments:

Post a Comment

Tutorials