Java ListIterator

ListIterator is an interface in java.util package used for traversing or iterating a list.

A ListIterator can be used for traversing following implementations of List interface.

Though a list can also be iterated using a plain iterator but ListIterator has some additional features which make it preferable.

Features of ListIerator
Following are some of the important features of ListIterator

1. Bidirectional

It can be used to iterate a list in both directions, that is, from first to last element or in forward direction and from last element to first or backwards.

2. Add and remove element

A ListIterator can be used to add or remove elements from a list while iterating.

3. Update element

ListIterator can also be used to change the value of an element. The element to be updated is the last element returned by ListIterator, this element may be in any of the two directions.
In simple words, the element returned by a call to its previous() or next() methods(discussed later)

3. Maintains position

A ListIterator manages a cursor position which  lies between two elements, previous and next where previous is the element before cursor position and next is the element after it.

From the above discussion, it is evident that a ListIterator can be used to modify a list while iterating without raising a ConcurrentModificationException.
Create ListIterator
As stated above, ListIterator is an interface, so it is not possible to create its object directly using any of the object creation methods in java.

However, each of the List based classes implement this interface in an inner class and provide a method which returns an object of this inner class.

ArrayList class
, for example, provides a method listIterator() which returns an object that implements ListIterator.
Example,

List<Integer> list = new ArrayList<>();
ListIterator<Integer> iterator = list.listIterator();

By default, listIterator() method returns a ListIterator which is positioned at the first list element but you can also get a ListIterator pointing to any list element by using listIterator(int) method.
It takes an integer argument which is the index of list element.

This method is an overloaded version of listIterator() method.

ListIterator example
Below is an example to traverse a list both in forward and reverse direction using a ListIterator.

import java.util.List;
import java.util.Arrays;
import java.util.ListIterator;

public class ListIteratorDemo {
   public static void main(String[] args) {
      // create a list
      List<Integer> list = Arrays.asList(new Integer[]{1, 2, 3, 4, 5, 6});
      // get list iterator
      ListIterator<Integer> listIterator = list.listIterator();
      System.out.println("Iterating in forward direction.");
      System.out.println("Elements are");
      // iterate forward
      while(listIterator.hasNext()) {
         Integer nextElement = listIterator.next();
         System.out.print(nextElement +" ");
      }
      System.out.println("\nIterating in backward direction.");
      System.out.println("Elements are");
      // iterate backwards
      while(listIterator.hasPrevious()) {
         Integer previousElement = listIterator.previous();
         System.out.print(previousElement +" ");
      }
   }
}

Above example creates a List from an array and gets a ListIterator over this list using listIterator method.
ListIterator iterates in forward direction using next() and hasNext() methods and in reverse or backward direction using previous() and hasPrevious() methods.
Output below shows that it can iterate in either directions.

Iterating in forward direction.
Elements are
1 2 3 4 5 6
Iterating in backward direction.
Elements are
6 5 4 3 2 1

ListIterator remove()
With ListIterator, you can also remove an element from the list using its remove() method.

remove() will return the element returned by a call to next() or previous() method. If remove() is called without calling next() or previous(), then an IllegalStateException will be thrown.
Example,

import java.util.List;
import java.util.Arrays;
import java.util.ListIterator;

public class ListIteratorDemo {
  public static void main(String[] args) {
    // create a list
    List<Integer>list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);
    list.add(5);
    // get list iterator
    ListIterator<Integer> listIterator = list.listIterator();
    System.out.println("Iterating in forward direction.");
    System.out.println("Elements are");
    // iterate forward
    while(listIterator.hasNext()) {
      Integer nextElement = listIterator.next();
      // remove 2 from list
      if(nextElement == 2) {
        listIterator.remove();
      }
      System.out.print(nextElement +" ");
    }
    System.out.println("\nIterating in backward direction.");
    System.out.println("Elements are");
    // iterate backwards
    while(listIterator.hasPrevious()) {
      Integer previousElement = listIterator.previous();
      System.out.print(previousElement +" ");
    }
  }
}

This prints

Iterating in forward direction.
Elements are
1 2 3 4 5
Iterating in backward direction.
Elements are
5 4 3 1

Note that 2 is removed from the list.
Also, note that this example does not convert an array to a list. This is because if you call remove() on a list created from Arrays.asList(), then it will throw an UnsupportedOperationException.

Reason is that Arrays.asList() creates an object of inner class of Arrays which does not support remove() method and invokes remove() of its parent class, AbstractList which throws this exception.
ListIterator add()
With ListIterator, you can add elements to a list with its add() method.
add() takes the element to be added as argument and the element is added before the element that would be returned by a call to next() and after the element returned by a call to previous().

Below is an example.

import java.util.List;
import java.util.Arrays;
import java.util.ListIterator;

public class ListIteratorDemo {
  public static void main(String[] args) {
    // create a list
    List<Integer>list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(4);
    list.add(5);
    System.out.println("Original list elements");
    // get list iterator
    ListIterator<Integer> listIterator = list.listIterator();
    
    int index = 0;
    // iterate forward
    while(listIterator.hasNext()) {
      if(index == 2) {
        // add 3 to list at index 2
        listIterator.add(3);
      }
      listIterator.next();
      ++index;
    }
    System.out.println("List elements are");
    // iterate backwards
    while(listIterator.hasPrevious()) {
      Integer previousElement = listIterator.previous();
      System.out.print(previousElement +" ");
    }
  }
}

We need to insert an element at the third position.
After each call to next(), an index is incremented which was initialized to 0 at start.
When index becomes 2, the element is inserted using add().
Below is the output to show that the element was inserted.

Original list elements
1 2 4 5
List elements are
5 4 3 2 1

ListIterator update element
It is also possible to modify the value of a list element using ListIterator with its set() method.
set() takes a value that needs to be updated and changes the element returned by a call to next() or previous().

Thus, if you call next() once and then set(35), this will update the value of first list element to 35.

Similarly, if the ListIterator is at the end of list, it calls previous() and then set(100), then the value of last list element will be changed to 100.
Listiterator methods
Though we have gone through the important and most used methods of a ListIterator, but here is a summary of those.

Method SignatureDescription
boolean hasNext()Checks if the iterator has any element left when iterating in forward direction.
Returns true if there is an element, false otherwise.
boolean hasPrevious()Checks if the iterator has any element left when iterating in backward direction.
Returns true if there is an element, false otherwise.
T next()Returns the next element when moving in forward direction.
T previous()Returns the next element when moving from backward direction.
int nextIndex()Returns the index of element which would be returned when next() is called.
int previousIndex()Returns the index of element which would be returned when previous() is called.
If iterator is positioned at the start of list, it returns -1.
void remove()Removes the element returned by a call to next() or previous().
If  either of these is not called before calling remove(), it throws an IllegalStateException.
void add(T)Adds the supplied element before the element returned by a call to next() and after the element that would be returned by a call to previous().
void set(T)Updates the element returned by next() or previous() to the supplied element.

Iterator vs ListIterator in java
This is a pretty obvious comparison and becomes a commonly asked interview question. Below is the list..

IteratorListIterator
This is the super class of ListIterator.Child class of Iterator.
Can iterate in forward direction only.Can iterate in both directions with next() and previous() methods.
Can not return index of an element.Can tell the index of element using its nextIndex() and previousIndex() methods.
Can not add an element.Can add an element using add() method.
Can remove an element using remove() method.Can remove an element using remove() method.
Can not update or modify element’s value.Can change element’s value using set() method.
Can be used on other collections such as Set.Can only be used on list.

Hope the article was informative regarding the importance and usage of ListIterator in java.

Leave a Reply