Author: Mohammad J Iqbal

Mohammad J Iqbal

Think about a very well known object for database interaction that we have used almost in every language and used for extracting data.

Answer: ResultSet

Do we know the internal data structure of ResultSet object? Mostly we don’t, unless someone was curious to look at the internal code of Resultset. But we trusted the hasNext() and next() methods to iterate ResultSet object :-) .

Iterator Pattern: the iterator pattern is a design pattern in which an iterator is used to traverse a container and access the container’s elements.

What problems can the Iterator design pattern solve?

  1. The elements of an aggregate object should be accessed and traversed without exposing its representation (data structures)

  2. New traversal operations should be defined for an aggregate object without changing its interface

I am using the custom LinkedList that I have written in my previous article.

The code below extends LinkedList , implements java.lang.Iterable interface and java.util.Iterator interface to achieve the goal.

The variable ‘lastReturned’ keeps track of the lastReturned Node

The variable ‘next’ points to the node to be iterated. Initially it can be assigned with first node of the linkedlist (default constructor()) or can be passed via this constructor. public IterableLinkedList(int nextIndex, Node next, int size)

The variable ‘nextIndex’ keeps track of the index of current node, initially can be assigned 0 or can be passed via above mentioned constructor along with size of the list.

The Iterable interface contains iterator() method which returns the concrete object that we need to iterate.

The Iterator interface contains methods hasNext() and next() that the concrete object implements, thus hiding the internal structure of the data structure to the iterator and outside world.


package com.spsoft.list;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class IterableLinkedList<E> extends LinkedList implements Iterable<E>, Iterator<E>{
    private Node<E> lastReturned;
    private Node<E> next;
    private int nextIndex;

    public IterableLinkedList(){
        this.nextIndex= 0;
        this.next = first;
    }
   
    public IterableLinkedList(int nextIndex, Node next, int size){
        this.nextIndex= nextIndex;
        this.next = next;
        this.size = size;
    }

    @Override
    public Iterator<E> iterator() {
        final Node<E> f = first;
        return new IterableLinkedList<>(nextIndex,f,super.size);
    }

    @Override
    public boolean hasNext() {
        return nextIndex < size;
    }

    @Override
    public E next() {
        if (!hasNext())
            throw new NoSuchElementException();
        lastReturned = next;
        next = next.next;
        nextIndex++;
        return lastReturned.item;
    }


}


Let’ test the class using IterableLinkedListTest class below.

The method printList() uses a for each loop to iterate the object list and method printListUsingIterator() uses iterator object which is a traditional way iterating.

Each time we needed to see the full list, we just called printList() or printListUsingIterator()

package com.spsoft.list;

import java.util.Iterator;

public class IterableLinkedListTest {
    static IterableLinkedList<Integer> list = new IterableLinkedList<Integer>();
    public static void printList(){
        System.out.println("Printing the updated list...");
        for (Integer integer : list) {
            System.out.print(integer + " ");
        }
        System.out.println();
    }
    public static void printListUsingIterator(){
        System.out.println("Printing the updated list...");
        Iterator<Integer> iter = list.iterator();
        while(iter.hasNext()){
            System.out.print(iter.next()+" ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        list.addLast(1);
        Node<Integer> node =  list.addLast(2);
        Node node3 =list.addLast(3);
        list.removeFirst();
        printList();
        list.addLast(4);
        printList();
        list.remove(node);
        printList();
        Node node5 = list.addLast(5);
        printList();
        list.remove(node5);
        printList();
        list.remove(node3);
        printList();
        list.removeFirst();
        printListUsingIterator();
        list.addLast(6);
        printList();

    }


}

Let’s look at the below output:

Output of the class LinkedListTest

Follow Mohammad J Iqbal on LinkedIn