Popular Searches
Popular Course Categories
Popular Courses

Using Iterator and ListIterator

Using Iterator and ListIterator

Maps, Iterators, and Collection Utilities

Using Iterator and ListIterator in Java

Course: Core Java Training

Topic: Using Iterator and ListIterator

Course Link: Core Java Training Course

Demo Link: Register for a Course Demo

Website: JustAcademy


1. Introduction to Iterator and ListIterator

Java provides Iterator and ListIterator interfaces to traverse elements stored in collections. Traversal means accessing elements one by one without needing to know the internal implementation of the collection.

These interfaces are part of the Java Collections Framework and are useful when processing, searching, removing, or updating elements in supported collections.

  • Iterator: Supports forward traversal and provides a controlled way to remove the last element returned by the iterator when removal is supported.
  • ListIterator: Extends Iterator and supports forward and backward traversal, element replacement, and insertion when the underlying list supports these operations.

Learning Objectives

  • Understand the purpose of iterators in Java.
  • Learn how to create and use an Iterator.
  • Understand the methods available in the Iterator interface.
  • Learn how ListIterator differs from Iterator.
  • Traverse lists in both forward and backward directions.
  • Add, replace, and remove list elements during iteration.
  • Understand common iterator errors and best practices.

2. What Is an Iterator in Java?

An Iterator is an interface in the java.util package that provides a standard way to traverse elements in a collection. It is commonly used with collections such as ArrayList, LinkedList, HashSet, and other implementations of the Collection interface.

An iterator maintains a traversal position and provides methods to determine whether more elements are available and retrieve the next element.

Key Characteristics of Iterator

  • Traverses elements in the forward direction.
  • Uses hasNext() to check whether another element is available.
  • Uses next() to retrieve the next element.
  • Can remove the last returned element through remove() when the operation is supported.
  • Supports forEachRemaining() for processing remaining elements.
  • Can be used with many collection types, including lists and sets.
  • Does not provide indexed access or backward traversal.

3. Syntax for Creating an Iterator

The iterator() method of a collection returns an Iterator for traversing its elements.

Iterator<DataType> iteratorName = collection.iterator();

For example:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorExample {
    public static void main(String[] args) {
        List<String> languages = new ArrayList<>();

        languages.add("Java");
        languages.add("Python");
        languages.add("JavaScript");

        Iterator<String> iterator = languages.iterator();

        while (iterator.hasNext()) {
            String language = iterator.next();
            System.out.println(language);
        }
    }
}

Output:

Java
Python
JavaScript

Explanation:

  • ArrayList stores the language names.
  • iterator() creates an iterator for the list.
  • hasNext() checks whether an element remains.
  • next() retrieves the next element and advances the iterator.
  • The loop ends when there are no more elements.

4. Important Methods of the Iterator Interface

Method Description Example
hasNext() Returns true if another element is available. iterator.hasNext()
next() Returns the next element and advances the iterator. iterator.next()
remove() Removes the last element returned by next(), if supported. iterator.remove()
forEachRemaining(action) Processes the remaining elements using the supplied action. iterator.forEachRemaining(System.out::println)

5. Understanding hasNext() and next()

The two most frequently used Iterator methods are hasNext() and next().

5.1 hasNext()

The hasNext() method returns true if another element is available. It does not advance the iterator.

List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);

Iterator<Integer> iterator = numbers.iterator();

System.out.println(iterator.hasNext());

Output:

true

5.2 next()

The next() method retrieves the next element and advances the iterator. Calling next() when no elements remain causes a NoSuchElementException.

System.out.println(iterator.next());
System.out.println(iterator.next());

Output:

10
20

Always use hasNext() to check whether an element remains before calling next() in a typical traversal loop.

6. Removing Elements Using Iterator

The remove() method removes the last element returned by the iterator's next() method. This is useful when filtering a collection during traversal.

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class IteratorRemoveExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();

        numbers.add(10);
        numbers.add(15);
        numbers.add(20);
        numbers.add(25);
        numbers.add(30);

        Iterator<Integer> iterator = numbers.iterator();

        while (iterator.hasNext()) {
            int number = iterator.next();

            if (number % 2 != 0) {
                iterator.remove();
            }
        }

        System.out.println(numbers);
    }
}

Output:

[10, 20, 30]

Explanation: The iterator examines each number and removes odd values through iterator.remove(). This avoids directly modifying the list's structure during the traversal.

Important Rules for remove()

  • Call next() before calling remove().
  • Only one removal is permitted for each successful call to next().
  • Calling remove() without a valid preceding next() call can cause an IllegalStateException.
  • Some collections or iterators do not support removal and may throw UnsupportedOperationException.

7. What Is ListIterator in Java?

ListIterator is an interface in the java.util package that extends Iterator. It is specifically designed for lists and provides additional capabilities beyond ordinary forward traversal.

Unlike Iterator, ListIterator can move both forward and backward through a list. It also provides methods to insert new elements, replace the last returned element, and obtain the indexes associated with its cursor position.

Key Characteristics of ListIterator

  • Supports forward traversal using hasNext() and next().
  • Supports backward traversal using hasPrevious() and previous().
  • Supports element replacement through set(), when supported.
  • Supports element insertion through add(), when supported.
  • Supports removal through remove(), when supported.
  • Provides nextIndex() and previousIndex().
  • Can be obtained from a List using listIterator() or listIterator(index).

8. Syntax for Creating a ListIterator

A ListIterator is obtained from a list by calling the listIterator() method.

ListIterator<DataType> iteratorName = list.listIterator();

To start traversal at a particular position, pass a valid index:

ListIterator<DataType> iteratorName = list.listIterator(index);

The index must be between zero and the list's size, inclusive. If the index is equal to the list size, the iterator starts at the end.

Example

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorExample {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>();

        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Mango");

        ListIterator<String> iterator = fruits.listIterator();

        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

Output:

Apple
Banana
Mango

9. Important Methods of the ListIterator Interface

Method Description
hasNext() Checks whether an element is available in the forward direction.
next() Returns the next element and moves forward.
hasPrevious() Checks whether an element is available in the backward direction.
previous() Returns the previous element and moves backward.
nextIndex() Returns the index of the element that a subsequent next() call would return.
previousIndex() Returns the index of the element that a subsequent previous() call would return.
add(element) Inserts an element at the iterator's current cursor position.
set(element) Replaces the last element returned by next() or previous().
remove() Removes the last element returned by next() or previous().

10. Forward Traversal Using ListIterator

Forward traversal processes elements from the beginning of the list toward the end. It works similarly to ordinary Iterator traversal.

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ForwardTraversal {
    public static void main(String[] args) {
        List<String> subjects = new ArrayList<>();

        subjects.add("Java");
        subjects.add("SQL");
        subjects.add("Python");

        ListIterator<String> iterator = subjects.listIterator();

        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

Output:

Java
SQL
Python

11. Backward Traversal Using ListIterator

ListIterator allows a list to be traversed in reverse order. To move backward from the end, first move the cursor to the end or finish a forward traversal.

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class BackwardTraversal {
    public static void main(String[] args) {
        List<String> colors = new ArrayList<>();

        colors.add("Red");
        colors.add("Green");
        colors.add("Blue");

        ListIterator<String> iterator =
            colors.listIterator(colors.size());

        while (iterator.hasPrevious()) {
            System.out.println(iterator.previous());
        }
    }
}

Output:

Blue
Green
Red

Explanation: Passing colors.size() starts the iterator at the end of the list. Each call to previous() returns the preceding element and moves the cursor backward.

12. Understanding the ListIterator Cursor

A ListIterator does not point directly at a current element. Its cursor is positioned between list elements. A list with three elements has four possible cursor positions.

Elements:  [A]   [B]   [C]
Positions:  ^     ^     ^     ^

At the start of the list, next() returns the first element. At the end, previous() returns the last element.

  • nextIndex() returns the index of the element that would be returned by the next call to next().
  • previousIndex() returns the index of the element that would be returned by the next call to previous().
  • At the beginning, previousIndex() returns -1.
  • At the end, nextIndex() returns the list size.

Example

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class IteratorIndexExample {
    public static void main(String[] args) {
        List<String> items = new ArrayList<>();

        items.add("A");
        items.add("B");
        items.add("C");

        ListIterator<String> iterator = items.listIterator();

        System.out.println(iterator.nextIndex());
        System.out.println(iterator.previousIndex());

        iterator.next();

        System.out.println(iterator.nextIndex());
        System.out.println(iterator.previousIndex());
    }
}

Output:

0
-1
1
0

13. Adding Elements Using ListIterator

The add() method inserts a new element at the cursor position. The inserted element appears after the element previously returned by previous() and before the element that would be returned by next().

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorAddExample {
    public static void main(String[] args) {
        List<String> languages = new ArrayList<>();

        languages.add("Java");
        languages.add("Python");

        ListIterator<String> iterator = languages.listIterator();

        iterator.next();
        iterator.add("SQL");

        System.out.println(languages);
    }
}

Output:

[Java, SQL, Python]

The iterator first moves past Java, then inserts SQL at its cursor position. The list becomes [Java, SQL, Python].

14. Replacing Elements Using ListIterator

The set() method replaces the last element returned by next() or previous(). It cannot be used until one of these methods has returned an element, and it must not follow an intervening add() or remove() operation.

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorSetExample {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>();

        names.add("Amit");
        names.add("Neha");
        names.add("Ravi");

        ListIterator<String> iterator = names.listIterator();

        while (iterator.hasNext()) {
            String name = iterator.next();

            if (name.equals("Neha")) {
                iterator.set("Priya");
            }
        }

        System.out.println(names);
    }
}

Output:

[Amit, Priya, Ravi]

This technique is useful when an existing list element must be updated while traversing the list.

15. Removing Elements Using ListIterator

ListIterator also supports remove(). It removes the last element returned by either next() or previous(), provided the list supports removal and the iterator is in a valid state.

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorRemoveExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();

        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        numbers.add(40);

        ListIterator<Integer> iterator = numbers.listIterator();

        while (iterator.hasNext()) {
            int number = iterator.next();

            if (number == 30) {
                iterator.remove();
            }
        }

        System.out.println(numbers);
    }
}

Output:

[10, 20, 40]

16. Starting ListIterator at a Specific Index

The overloaded listIterator(index) method lets you begin traversal from a specific position in the list. The index must be between zero and the list size, inclusive.

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class StartAtIndexExample {
    public static void main(String[] args) {
        List<String> cities = new ArrayList<>();

        cities.add("Mumbai");
        cities.add("Pune");
        cities.add("Delhi");
        cities.add("Chennai");

        ListIterator<String> iterator = cities.listIterator(2);

        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

Output:

Delhi
Chennai

Because the starting index is 2, the first call to next() returns the element at index 2, which is Delhi.

17. Difference Between Iterator and ListIterator

Feature Iterator ListIterator
Interface relationship Basic traversal interface Extends Iterator
Supported collections Many collection types, including lists and sets Lists only
Traversal direction Forward only Forward and backward
Read next element Yes, using next() Yes, using next()
Read previous element No Yes, using previous()
Remove elements Yes, if supported Yes, if supported
Add elements during iteration No add() method Yes, using add(), if supported
Replace the last returned element No set() method Yes, using set(), if supported
Index information Not provided nextIndex() and previousIndex()
Starting position Normally starts at the beginning Can start at a specified valid index

18. Using forEachRemaining()

The forEachRemaining() method processes every remaining element using a specified action. It is available through the Iterator interface and therefore can also be used with ListIterator.

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ForEachRemainingExample {
    public static void main(String[] args) {
        List<String> tools = new ArrayList<>();

        tools.add("Git");
        tools.add("Maven");
        tools.add("Gradle");

        Iterator<String> iterator = tools.iterator();

        iterator.forEachRemaining(System.out::println);
    }
}

Output:

Git
Maven
Gradle

After processing the remaining elements, the iterator reaches the end of the collection.

19. Common Iterator Errors and Exceptions

Error or Exception Cause How to Avoid It
NoSuchElementException Calling next() or previous() when no element is available in that direction. Check hasNext() or hasPrevious() first.
IllegalStateException Calling remove() or set() when the iterator is not in a valid state. Follow the required next()/previous() and modification rules.
UnsupportedOperationException Using add(), remove(), or set() when the underlying collection does not support that operation. Use a collection that supports the required modification.
ConcurrentModificationException Some fail-fast iterators detect structural changes made outside the iterator while iterating. Use the iterator's supported modification methods or a suitable concurrent collection.
IndexOutOfBoundsException Passing an invalid index to listIterator(index). Use an index between 0 and list.size(), inclusive.

20. Understanding ConcurrentModificationException

Many standard collection iterators are fail-fast. They may throw ConcurrentModificationException when the collection is structurally modified outside the iterator during iteration. This behavior is best-effort and should not be treated as a synchronization guarantee.

Incorrect Example

List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);

Iterator<Integer> iterator = numbers.iterator();

while (iterator.hasNext()) {
    Integer number = iterator.next();

    if (number == 20) {
        numbers.remove(number);
    }
}

This code modifies the list directly instead of using the iterator to remove the element. A fail-fast iterator may detect the structural change and throw ConcurrentModificationException.

Correct Example

Iterator<Integer> iterator = numbers.iterator();

while (iterator.hasNext()) {
    Integer number = iterator.next();

    if (number == 20) {
        iterator.remove();
    }
}

Using iterator.remove() keeps the removal operation coordinated with the iterator.

21. Practical Example: Managing a Student List

This example demonstrates using ListIterator to update student names, add a new entry, and traverse the list in reverse.

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class StudentListManager {
    public static void main(String[] args) {
        List<String> students = new ArrayList<>();

        students.add("Aarav");
        students.add("Priya");
        students.add("Rahul");

        ListIterator<String> iterator = students.listIterator();

        while (iterator.hasNext()) {
            String name = iterator.next();

            if (name.equals("Priya")) {
                iterator.set("Priya Sharma");
            }

            if (name.equals("Rahul")) {
                iterator.add("Neha");
            }
        }

        System.out.println("Updated student list: " + students);

        System.out.println("Reverse traversal:");
        ListIterator<String> reverse = students.listIterator(students.size());

        while (reverse.hasPrevious()) {
            System.out.println(reverse.previous());
        }
    }
}

Output:

Updated student list: [Aarav, Priya Sharma, Rahul, Neha]
Reverse traversal:
Neha
Rahul
Priya Sharma
Aarav

Explanation: The program uses set() to replace Priya with Priya Sharma, then uses add() to insert Neha after Rahul. A second ListIterator starts at the end and traverses the list backward.

22. Best Practices for Iterator and ListIterator

  • Use hasNext() before calling next() in a standard forward loop.
  • Use hasPrevious() before calling previous().
  • Use Iterator when forward traversal is sufficient.
  • Use ListIterator when a list requires bidirectional traversal or insertion and replacement during iteration.
  • Use iterator.remove() or listIterator.remove() for supported removals during traversal.
  • Do not call remove() or set() before a valid call to next() or previous().
  • Remember that not every collection supports every modification operation.
  • Avoid modifying a collection directly while iterating over it with a fail-fast iterator.
  • Use generics to ensure type safety, such as Iterator<String>.
  • Prefer the enhanced for loop for simple read-only traversal when explicit iterator operations are not needed.

23. Hands-On Exercises

Exercise 1: Display List Elements

Create an ArrayList of five programming languages and display all elements using Iterator.

Exercise 2: Remove Odd Numbers

Create a list of integers and use Iterator to remove all odd numbers.

Exercise 3: Reverse a List

Create a list of city names and use ListIterator to display them in reverse order.

Exercise 4: Replace an Element

Use ListIterator to replace a specific name in a list with a new name.

Exercise 5: Insert at a Cursor Position

Create a list of subjects and use ListIterator to insert a new subject after a selected element.

Exercise 6: Index Tracking

Use nextIndex() and previousIndex() to display the cursor's index before and after traversal operations.

24. Mini Project: To-Do List Manager

Objective: Create a simple To-Do List Manager using an ArrayList and ListIterator.

Project Requirements

  • Store task names in an ArrayList.
  • Display tasks using Iterator.
  • Remove completed tasks during traversal.
  • Replace an existing task description using ListIterator.
  • Insert a new task at a specific cursor position.
  • Display tasks in reverse order.

Sample Implementation

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class TodoListManager {
    public static void main(String[] args) {
        List<String> tasks = new ArrayList<>();

        tasks.add("Complete Java notes");
        tasks.add("Practice collections");
        tasks.add("Submit assignment");
        tasks.add("Review Iterator");

        Iterator<String> iterator = tasks.iterator();

        while (iterator.hasNext()) {
            String task = iterator.next();

            if (task.equals("Submit assignment")) {
                iterator.remove();
            }
        }

        ListIterator<String> listIterator = tasks.listIterator();

        while (listIterator.hasNext()) {
            String task = listIterator.next();

            if (task.equals("Review Iterator")) {
                listIterator.set("Revise Iterator and ListIterator");
                listIterator.add("Practice coding exercises");
            }
        }

        System.out.println("Final task list:");
        for (String task : tasks) {
            System.out.println(task);
        }

        System.out.println("Tasks in reverse order:");
        ListIterator<String> reverse = tasks.listIterator(tasks.size());

        while (reverse.hasPrevious()) {
            System.out.println(reverse.previous());
        }
    }
}

This project combines forward traversal, safe iterator-based removal, element replacement, insertion, and backward traversal.

25. Interview Questions and Answers

Q1. What is an Iterator in Java?

Iterator is an interface used to traverse collection elements in the forward direction. It provides methods such as hasNext(), next(), and remove().

Q2. What is ListIterator?

ListIterator extends Iterator and is designed for lists. It supports forward and backward traversal, element insertion, element replacement, removal, and index information.

Q3. What is the main difference between Iterator and ListIterator?

Iterator supports forward traversal across many collection types. ListIterator is list-specific and supports backward traversal and additional modification operations.

Q4. Can Iterator traverse a list backward?

No. Iterator only supports forward traversal. Use ListIterator when backward traversal is required.

Q5. Can ListIterator modify a list?

Yes. It can insert, replace, or remove elements when the underlying list supports the corresponding operations and the iterator is in a valid state.

Q6. What does hasNext() do?

It returns true when another element is available in the forward direction, without advancing the iterator.

Q7. What happens when next() is called after the end?

It throws NoSuchElementException when no element remains.

Q8. What is the purpose of listIterator(index)?

It creates a ListIterator positioned at the specified valid index, so the next call to next() returns the element at that index.

Q9. Why can ConcurrentModificationException occur?

Some fail-fast iterators detect structural modifications made outside the iterator during traversal. Use supported iterator modification methods or an appropriate concurrent collection.

Q10. Can all iterators remove elements?

No. Removal is an optional operation. An iterator may throw UnsupportedOperationException if removal is not supported by the underlying collection.

26. Quick Revision Checklist

  • Iterator belongs to the java.util package.
  • iterator() obtains an Iterator from a collection.
  • hasNext() checks for another forward element.
  • next() retrieves the next element.
  • remove() removes the last returned element when supported.
  • ListIterator extends Iterator and works with lists.
  • ListIterator supports previous() and hasPrevious().
  • add() inserts at the cursor position.
  • set() replaces the last returned element.
  • nextIndex() and previousIndex() provide index information.
  • Unsupported modification operations can throw UnsupportedOperationException.
  • Invalid iterator state can cause IllegalStateException.
  • Use iterator-based removal rather than directly modifying a collection during traversal.

27. Conclusion

Iterator and ListIterator are essential tools for traversing collections in Java. Iterator provides simple forward traversal and controlled removal, making it useful for processing lists, sets, and other collections.

ListIterator provides additional capabilities for lists, including backward traversal, cursor indexes, insertion, and replacement. Understanding their methods, valid usage rules, and common exceptions helps you write safer and more maintainable Java programs.

Practice the examples and mini project to build confidence in collection traversal and modification.

Continue Learning: Explore the Core Java Training course, register for a course demo, or visit the JustAcademy website.

Previous Next
whatsapp