Introduction

This tutorial explains how to implement java.lang.Iterable on a class to enable for-each loop based iteration through the collection of objects stored in that class.

Table of Content :

We will see Iterable and for-each loop are related, Then we will see how to implement Iterable, and finally shows a Java code example showing Iterable interface implementation and implementing class’ use in a for-each.

The Collection interface extends Iterable and hence all child classes of Collection also implement Iterable. Iterable has only one method that produces an Iterator:

Every class that implements Iterable interface appropriately, can be used in the enhanced For loop (for-each loop). The need to implement the Iterator interface arises while designing custom data structures.

 
 
   for(Item item: customDataStructure) {
    // do stuff
}
 

How to implement Iterable interface?

To implement an iterable data structure, we need to:

Implement an Iterable interface along with its methods in the said Data Structure.

Create an Iterator class which implements Iterator interface and corresponding methods.

 
  class MyClass implements Iterable<> { 
	
	// code for data structure 
	public Iterator<> iterator() { 
		return new CustomIterator<>(this); 
	} 
} 
 
 
 

 
 class CustomIterator<> implements Iterator<> { 
	
	// constructor 
	CustomIterator<>(CustomDataStructure obj) { 
		// initialize cursor 
	} 
	
	// Checks if the next element exists 
	public boolean hasNext() { 
	} 
	
	// moves the cursor/iterator to next element 
	public T next() { 
	} 
	
	// Used to remove an element. Implement only if needed 
	public void remove() { 
		// Default throws UnsupportedOperationException. 
	} 
} 

 
 

How next() and hasNext() work?

To implement an Iterator, we need a cursor or pointer to keep track of which element we currently are on. Depending on the underlying data structure, we can progress from one element to another. This is done in the next() method which returns the current element and the cursor advances to next element.

Before advancing the pointer, we check whether the next element exists. i.e. we can imagine the behind-the-scenes code as follows:

 
 While(iterator.hasNext()) { //if next element exists
    next(); // advance the pointer
}
 
 

Initializing the cursor

The cursor initialization completely depends on the data structure. For example, in a linked list we would initialize cursor to the head element. In an array list, we would initialize cursor to the 0th element. From the point of view of implementation:

If the Iterator class is implemented as an inner class, we can simply use “this” keyword (e.g. cursor = CustomDataStructure.this.element) to access the desired element.

If the Iterator class is implemented as a separate class, we can pass this object of the data structure to the iterator class constructor as demonstrated in the example below.

Custom Iterable Data Structure

 
 
   
import static java.lang.String.format;
import java.util.*;
 
public class Student {
  
  //@Getter @Setter @toString()
   private String firstName, 
   private String lastName;
   private int rollNumber;
  
   public Student(){ }
   public Student(String firstName, String lastName, int rollNumber) {
      this.firstName = firstName;
      this.lastName = lastName;
      this.rollNumber = rollNumber;
   }
   
}
 

Now let us look at StudentArrayList implementation which implements the Iterator interface. The iterator method is overridden to return the Student arrayList iterator.

 
 
 class StudentArrayList implements Iterable {
   private List students;
  
   public StudentArrayList() {
      students = new ArrayList();
   }
   public StudentArrayList(int rollNumber) {
      students = new ArrayList(rollNumber);
   }
   public void addStudent(Student student) {
      students.add(student);
   }
  
  public void removeStudent(Student student) {
      students.remove(student);
   }
   public int studentsListSize() {
      return students.size();
   }
   @Override
   public Iterator iterator() {
      return students.iterator();
   }

}
 
 
   public class StudentArrayListTester {
  
   public static void main(String[] args) {
  
      Student stud1 = new Student("Chanakya", "Vishnugupt", 1);
      Student stud2 = new Student("Stuard","Fleming", 2);
      Student stud3 = new Student("Anna","Smith", 10);
   
      StudentArrayList studList = new StudentArrayList();
  
      studList.addStudent(stud1);
      studList.addStudent(stud2);
      studList.addStudent(stud3);
  
      for (Student stud : studList) {
         System.out.println(stud);
      }
   }
}
  
  First Name: Chanakya Last Name: Vishnugupt rollNumber: 1
  First Name: Stuard Last Name: Fleming rollNumber: 2
  First Name: Anna Last Name: Smith rollNumber: 10
 
 

We see more details about Iterable

Iterable is one of the main interfaces of the collection classes in Java.

The Collection interface extends Iterable and hence all child classes of Collection also implement Iterable.

Iterable has only one method that produces an Iterator:

 
 
   public interface Iterable {
    public Iterator iterator();    
}
 

Iterator can then be used to iterate over the elements in the Iterable.

All classes that implement Iterable are eligible for the for-each loop in Java.

Mostly the Iterable will be an instance of Collection, such as a List or a Set.

In this case we can check the type of the Iterable and call size() method on it to get the number of elements.

 
 
if (data instanceof Collection) {
    return ((Collection) data).size();
}
    

The call to size() is usually much faster than iterating through the entire collection.

using Java 8, we can create a Stream from the Iterable. The Stream object can be used to get the count of elements in the Iterable.

return StreamSupport.stream(data.spliterator(), false).count();

The Apache Commons Collections library has a nice IterableUtils class that provides static utility methods for Iterable instances.

Before we start, we need to import the latest dependencies from Gradle or Maven

 
 
 
    org.apache.commons
    commons-collections4
    4.1
  
 

In the above tutorial, we understood how Iterable interface can be implemented in a class holding a collection of objects. We then saw with a Java code example showing how such a collection can be iterated through using the enhanced for-each loop.