Design pattern "Iterator"

Let's learn what is the "Iterator" design pattern πŸ”„
Tuesday, July 30, 2024

Real world example

In a music player, you often have a playlist which is essentially a collection of songs. Now, one of the most common operations on this playlist is to go through the songs one by one in a certain order (maybe sequentially or in shuffle mode). This is where an iterator becomes very useful.

Here’s a simplified example:

public class MusicPlayer {
public static void main(String[] args) {
List<Song> songs = new ArrayList<>();
songs.add(new Song("Song 1"));
songs.add(new Song("Song 2"));
songs.add(new Song("Song 3"));
Playlist playlist = new Playlist(songs);
for (Song song : playlist) {
System.out.println("Now playing: " + song.getName());
}
}
}

The iterator pattern here allows the MusicPlayer to not worry about how the Playlist is implemented. The playlist could be a simple list, a queue, a stack, or any other data structure that fits the requirements. The MusicPlayer simply asks for the next song from the iterator. This makes the MusicPlayer code simpler, more readable, and easier to maintain. It abstracts away the details of accessing elements from a collection.

Note: We can use a while loop too to iterate !

In plain words

It presents a way to access the elements of an object without exposing the underlying presentation.

Wikipedia definition

In object-oriented programming, the iterator pattern is a design pattern in which an iterator is used to traverse a container and access the container’s elements. The iterator pattern decouples algorithms from containers; in some cases, algorithms are necessarily container-specific and thus cannot be decoupled.

Programmatic example

In this example, MyCollection is a collection that implements the Iterable interface. MyIterator is an inner class of MyCollection that implements the Iterator interface. The main method creates a MyCollection object and uses a for-each loop to iterate over its elements. The hasNext method checks if there are more elements to iterate over, and the next method returns the next element. This is a basic example of the Iterator design pattern in Java. In a real-world application, the collection could be any type of data structure, such as a list, set, or map, and the iterator could be used to implement complex traversal algorithms.

import java.util.Iterator;
class MyCollection implements Iterable<String> {
private String[] items;
public MyCollection(String[] items) {
this.items = items;
}
@Override
public Iterator<String> iterator() {
return new MyIterator();
}
class MyIterator implements Iterator<String> {
private int index = 0;
@Override
public boolean hasNext() {
return index < items.length;
}
@Override
public String next() {
return items[index++];
}
}
}
public class Main {
public static void main(String[] args) {
String[] items = {"Item 1", "Item 2", "Item 3"};
MyCollection collection = new MyCollection(items);
for (String item : collection) {
System.out.println(item);
}
// ---------------
// OR
// ---------------
// Create an iterator for the collection
Iterator<String> iterator = collection.iterator();
// Use a while loop to iterate over the items
while (iterator.hasNext()) {
String item = iterator.next();
System.out.println(item);
}
}
}

Diagram

Loading graph...

Some other examples

  1. File System Traversal: When you need to traverse through a file system, which can be seen as a tree-like structure (directories contain other directories and files), an iterator can be used to traverse through all the files.
  2. Social Networking Platforms: In a social network, iterators can be used to traverse through the list of friends, followers, posts, comments, etc.
  3. Music Player: In a playlist of a music player, an iterator can be used to go through each song one by one.
  4. Database Query Result: When a database query returns a set of records, an iterator can be used to go through each record.
  5. Image Pixel Processing: In image processing, an iterator can be used to traverse through each pixel of an image for processing.
  6. Text Processing: In a text document, an iterator can be used to traverse through each character or word in the document.
  7. Graph Traversal: In graph data structures (used in maps, social networks etc.), iterators can be used to traverse nodes using algorithms like Depth-First Search (DFS) or Breadth-First Search (BFS).
  8. Data Structures: In data structures like arrays, linked lists, trees, hash maps, etc., iterators are used to traverse through the elements.
  9. Web Scraping: When scraping data from a website, an iterator can be used to go through each HTML element.
  10. Game Development: In a game, an iterator can be used to cycle through game objects or game states.

Recommended articles