Difference between an Iterator and ListIterator in Java
This post will discuss the difference between an Iterator and ListIterator interface in Java, which is used for traversing over elements of a Collection.
1. Overview of the Iterator interface
The Iterator interface is a fundamental part of the Java Collections Framework and available for all Collection implementations, such as List, Set, Queue, Deque, and also in all implemented classes of Map interface. It allows us to access elements in a collection sequentially without knowing its underlying structure. It offers three primary methods: hasNext(), next(), and remove(), which can be used to traverse collection only in the forward direction.
|
1 2 3 4 5 6 7 8 |
public interface Iterator<E> { boolean hasNext(); E next(); default void remove() { throw new UnsupportedOperationException("remove"); } // … } |
Using the hasNext() and the next() methods, we can check if there are more elements and move to those elements. However, the remove() method removes from the collection the last element returned by the next() method. Further, as we can see, the remove() method is a default method, so it’s optional. Its implementation depends on the underlying collection. For example:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; class Main { public static void main(String[] args) { List<String> inputList = new ArrayList<>(Arrays.asList("1", "2", "3", "4", "5")); Iterator<String> it = inputList.iterator(); while (it.hasNext()) { String e = it.next(); System.out.println(e); // 1, 2, 3, … if ("3".equals(e) || "5".equals(e)) { it.remove(); } } } } |
2. Overview of the ListIterator interface
The ListIterator interface is a subtype of Iterator. Therefore, all the features Iterator offers are also available in ListIterator. As its name implies, ListIterator is used explicitly with lists. Apart from the three methods from the Iterator interface (hasNext(), next(), and remove()), the ListIterator interface has a set of new methods to traverse the list in both forward and backward directions.
|
1 2 3 4 5 6 7 8 9 10 11 |
public interface ListIterator<E> extends Iterator<E> { boolean hasNext(); E next(); void remove(); boolean hasPrevious(); E previous(); int nextIndex(); int previousIndex(); void set(E e); void add(E e); } |
Let’s take a closer look at these new methods:
1. previous() and previousIndex() method
The previous() method returns the previous element in the list and moves the cursor position backward. This method can be used to traverse the list in backward direction. The previousIndex() method returns the index of the element that would be returned by a subsequent call to previous(). For example:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.Arrays; import java.util.List; import java.util.ListIterator; class Main { public static void main(String[] args) { List<String> names = Arrays.asList("Aaron", "Bella", "Casey"); ListIterator<String> lit = names.listIterator(names.size()); while (lit.hasPrevious()) { System.out.println(lit.previousIndex() + ": " + lit.previous()); } // Output: // 2: Casey // 1: Bella // 0: Aaron } } |
2. nextIndex() method
The nextIndex() method returns the index of the element that would be returned by a subsequent call to next(). For example:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.Arrays; import java.util.List; import java.util.ListIterator; class Main { public static void main(String[] args) { List<String> names = Arrays.asList("Aaron", "Bella", "Casey"); ListIterator<String> lit = names.listIterator(); while (lit.hasNext()) { System.out.println(lit.nextIndex() + ": " + lit.next()); } // Output: // 0: Aaron // 1: Bella // 2: Casey } } |
3. hasPrevious() method
The hasPrevious() method returns true if there are more elements to traverse in backward direction. For example:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import java.util.Arrays; import java.util.List; import java.util.ListIterator; class Main { public static void main(String[] args) { List<String> names = Arrays.asList("Aaron", "Bella", "Casey"); ListIterator<String> lit = names.listIterator(names.size()); if (lit.hasPrevious()) { System.out.println(lit.previous()); // Casey } } } |
4. set() method
The set() method replaces the last element returned by next() or previous() with the specified element. For example:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.Arrays; import java.util.List; import java.util.ListIterator; class Main { public static void main(String[] args) { List<String> names = Arrays.asList("Aaron", "Bella", "Casey"); ListIterator<String> lit = names.listIterator(); while (lit.hasNext()) { String name = lit.next(); if ("Bella".equals(name)) { lit.set("Robert"); } } System.out.println(names); // [Aaron, Robert, Casey] } } |
5. The add() method
The add() method inserts the specified element into the list at the current position of the cursor. The element is inserted before the element that would be returned by next(), if any, and after the element that would be returned by previous(), if any. The cursor is moved forward after the insertion. For example:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.ListIterator; class Main { public static void main(String[] args) { List<String> names = new ArrayList<>(Arrays.asList("Aaron", "Bella", "Casey")); ListIterator<String> lit = names.listIterator(); while (lit.hasNext()) { String name = lit.next(); if ("Bella".equals(name)) { lit.add("David"); } } System.out.println(names); // [Aaron, Bella, David, Casey] } } |
3. Differences between Iterator and ListIterator
Iterator and ListIterator are both useful interfaces for iterating over lists in Java, but they have some differences and trade-offs that we must understand:
- The major difference between an
IteratorandListIteratorlies in the way they traverse the Collection. WithIterator, we can only move in forward direction using itshasNext()andnext()method while withListIterator, we can traverse the list in either direction.ListIteratorprovideshasNext()andnext()method to travel in forward direction andhasPrevious()andprevious()method to travel in backward direction. - The
ListIteratorallows us to modify the list during iteration, using itsset()method. This is not feasible with anIterator. - While traversing a list using
ListIterator, we can add a new element at any point of time using itsadd()method. This method is not available in theIteratorclass. - Using
Iterator, we cannot obtain the iterator’s current position in the list. On the other hand, aListIteratorcan return the index of next or previous elements while traversing a list using itsnextIndex()andpreviousIndex(), respectively. - An
Iteratorcan be used with any collection, whereasListIteratorcan only be used with lists.
4. What to use and when?
As we have seen, Iterator and ListIterator are both useful interfaces for iterating over lists in Java. Here are some general recommendations on how to choose between them:
- If you need to traverse a list in forward direction and perform read and remove operations, we should use Iterator.
- If you need to traverse a list in both forward and backward directions and perform read, remove, add, and replace operations, we should use ListIterator.
That’s all about the differences between an Iterator and a ListIterator in Java.
Thanks for reading.
To share your code in the comments, please use our online compiler that supports C, C++, Java, Python, JavaScript, C#, PHP, and many more popular programming languages.
Like us? Refer us to your friends and support our growth. Happy coding :)