Custom Iterator Interface in Salesforce Apex

In Salesforce Apex development, an iterator passes through every item in a collection. In conditions such as loop conditions, we provide some means to pass through the collection, that is, an iterator in Apex.

In this Salesforce tutorial, we will learn about iterators and how to use the Iterator Interface in Salesforce Apex.

What are Iterators in Salesforce Apex?

In the Salesforce Apex code structure, an iterator is a pattern that allows us to access the elements of a collection. These iterators help navigate each item in the data, which is particularly useful when working with large amounts of data in Salesforce.

In Salesforce Apex, iterators are generally used to loop through data collections, such as a list of records or a map of key-value pairs. While Salesforce provides several built-in iterators, such as the List and Set iterators, sometimes we need to create a custom iterator to meet specific business requirements.

Salesforce Apex Iterators Methods

An Iterator Interface in Apex typically includes two primary methods: hasNext() and next().

  • hasNext() Method: The hasNext() method determines if more elements remain in the collection. It returns the output in boolean form: if there are more elements to process in the collection, it returns True; otherwise, it returns False.
  • next() Method: The next() method is used in the batchable classes that handle large sets of records in bulk data processing. In batch Apex, records are processed in small parts called “batches.” The next() method helps retrieve the next set of documents in the batch.

Creating and Implementing a Custom Iterator in Salesforce Apex

In the steps below, we will create custom iterators for Salesforce Apex using the hasnext() and next() methods.

Let’s consider an example where we create an iterator that traverses a list of account records. We’ll define a class that implements the ‘Iterator<Account>‘ interface for this.

Apex code for the Custom iterator class:

public class AccountIterator implements Iterator<Account> {
    private List<Account> accounts;  
    private Integer currentIndex = 0; 

    public AccountIterator(List<Account> accounts) {
        this.accounts = accounts;
    }
    public Boolean hasNext() {
        return currentIndex < accounts.size();
    }

    public Account next() {
        if (!hasNext()) {
            throw new NoSuchElementException('No more accounts to iterate.');
        }
        return accounts[currentIndex++];
    }
}

The AccountIterator class implements the Iterator interface, making it a custom iterator specifically for Account objects. It uses a list to store the accounts and an integer currentIndex to track the current position in the list.

Use of Custom Iterator in Apex Class

Now, we will use the custom iterator to iterate through accounts in a collection. The Apex code below exemplifies how to use the custom iterator in a class or method.

public class AccountProcessor {
    public static void processAccounts(List<Account> accountList) {
        AccountIterator accountIterator = new AccountIterator(accountList);

        while (accountIterator.hasNext()) {
            Account acc = accountIterator.next();
            System.debug('Processing Account: ' + acc.Name);
        }
    }
}

In the above code, the Constructor initializes the iterator with a list of account objects.

  • hasNext() Method: Returns true if more accounts are needed.
  • next() Method: Returns the following account in the list and advances the index. Throws a NoSuchElementException if there are no more elements to iterate.

Calling and testing the Iterator method in an anonymous window.

List<Account> accountList = [SELECT Id, Name FROM Account LIMIT 10];
AccountProcessor.processAccounts(accountList);

After running the anonymous code, we can see the list of retrieved accounts in the debug window.

Custom iterators in Salesforce Apex

This way, we can create and use a custom iterator in Apex to process a collection of object records.

Batch Apex Implementation Using Iterables in Salesforce Apex

In Salesforce, batch Apex processes large amounts of data asynchronously by dividing it into smaller parts. While the default method involves using Database.queryLocator to fetch records, there are situations where you might want more control over how data is retrieved and processed.

Using iterable in batch Apex allows us to create custom logic for retrieving and iterating over records. This is particularly useful when performing additional processing or defining specific rules for grouping records before passing them to the execute method.

Let’s understand batch Apex implementation using an iterable that processes Account records with a specific condition.

Creating the Iterable APEX class

First, we will create the Iterable class, which implements the Iterable<Sobject> interface and defines the logic to provide data for the batch.

public class AccountIterable implements Iterable<Account> {
    public Iterator<Account> iterator() {
        return new AccountIterator();
    }

    public class AccountIterator implements Iterator<Account> {
        private List<Account> accounts;
        private Integer currentIndex = 0;

        public AccountIterator() {
            accounts = [SELECT Id, Name FROM Account WHERE Industry = 'Technology'];
        }

        public Boolean hasNext() {
            return currentIndex < accounts.size();
        }

        public Account next() {
            if (!hasNext()) {
                throw new LimitException('No more elements');
            }
            return accounts[currentIndex++];
        }
    }
}

The Batch Apex class processes records provided by Iterable.

public class AccountBatch implements Database.Batchable<Account> {
    public Iterable<Account> start(Database.BatchableContext bc) {
        System.debug('Batch Start Method Invoked');
        return new AccountIterable();
    }

    public void execute(Database.BatchableContext bc, List<Account> scope) {
        System.debug('Batch Execute Method Invoked');
        System.debug('Number of Records in Scope: ' + scope.size());

        for (Account acc : scope) {
            System.debug('Processing Account: ' + acc.Id + ' - ' + acc.Name);
            acc.Name = acc.Name + ' - Updated';
        }
        
        update scope;

        System.debug('Batch Execute Method Completed for Scope');
    }

    public void finish(Database.BatchableContext bc) {
        System.debug('Batch Finish Method Invoked');
        System.debug('Batch Processing Completed Successfully');
    }
}

Call the method using the anonymous code below.

AccountBatch batch = new AccountBatch();
Database.executeBatch(batch, 10); 

Output:

Batch Apex Implementation Using Iterables in Salesforce

The iterable method is executed successfully, and in the debug window, we can see the debug of the executed steps. The start method logs the batch that has started.

The execution method logs each batch’s execution, including the number of records being processed and the details of each record within the scope. Finally, finish method logs when batch processing is complete.

This way, we can execute the batch Apex implementation using the iterables in Salesforce Apex.

You may also like to read:

Agentforce in Salesforce

DOWNLOAD FREE AGENTFORCE EBOOK

Start with AgentForce in Salesforce. Create your first agent and deploy to your Salesforce Org.

Salesforce flows complete guide

FREE SALESFORCE FLOW EBOOK

Learn how to work with flows in Salesforce with 5 different real time examples.