Shiklo Programming
EN
  • English
  • Español
  • Português
  • Deutsch
  • Français
  • 日本語
  • हिन्दी

Java Iterator

Every collection you have met, ArrayList, LinkedList, HashSet and the key sets of a HashMap, can give you an iterator: an object that walks through the items one at a time. The for-each loop uses an iterator behind the scenes. Using one directly gives you one extra power: removing items safely while you walk.

hasNext and next

iterator() returns an Iterator. hasNext() tells whether there is another item, and next() returns it and moves on:

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

public class Main {
    public static void main(String[] args) {
        List<String> colours = new ArrayList<>(List.of("red", "green", "blue"));
        Iterator<String> it = colours.iterator();
        while (it.hasNext()) {
            String c = it.next();
            System.out.println(c.toUpperCase());
        }
    }
}
Output
RED
GREEN
BLUE

This loop does the same as for (String c : colours). In fact, the for-each loop works with any object that can give an iterator, which is why it works with every collection.

Removing while looping

Removing items from a list inside a for-each loop over that list confuses its hidden iterator, and Java stops with an exception:

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

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>(List.of(4, 7, 10, 13));
        for (int n : numbers) {
            if (n % 2 == 0) {
                numbers.remove(Integer.valueOf(n));
            }
        }
        System.out.println(numbers);
    }
}
Output
Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$Itr.checkForComodification(Unknown Source)
	at java.base/java.util.ArrayList$Itr.next(Unknown Source)
	at Main.main(Main.java:7)

The safe way is to remove through the iterator itself, with its remove() method, which removes the item that next() returned last:

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

public class Main {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>(List.of(4, 7, 10, 13, 16));
        Iterator<Integer> it = numbers.iterator();
        while (it.hasNext()) {
            if (it.next() % 2 == 0) {
                it.remove();
            }
        }
        System.out.println(numbers);
    }
}
Output
[7, 13]

For this common case, numbers.removeIf(n -> n % 2 == 0) is even shorter; it uses a lambda.

Iterating over a map

A map has no iterator of its own, but its keySet(), values() and entrySet() do. Removing through the entry set's iterator removes the pair from the map:

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class Main {
    public static void main(String[] args) {
        Map<String, Integer> stock = new TreeMap<>(Map.of("pen", 0, "book", 4, "ink", 0, "bag", 2));
        Iterator<Map.Entry<String, Integer>> it = stock.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, Integer> e = it.next();
            if (e.getValue() == 0) {
                System.out.println("Sold out: " + e.getKey());
                it.remove();
            }
        }
        System.out.println(stock);
    }
}
Output
Sold out: ink
Sold out: pen
{bag=2, book=4}

ListIterator: both directions and changes

Lists offer a ListIterator, which can also go backwards and replace the current item with set:

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

public class Main {
    public static void main(String[] args) {
        List<String> names = new ArrayList<>(List.of("asha", "ben", "chitra"));
        ListIterator<String> it = names.listIterator();
        while (it.hasNext()) {
            String n = it.next();
            it.set(n.substring(0, 1).toUpperCase() + n.substring(1));
        }
        System.out.println(names);
        while (it.hasPrevious()) {
            System.out.print(it.previous() + " ");
        }
        System.out.println();
    }
}
Output
[Asha, Ben, Chitra]
Chitra Ben Asha 

Practice exercises

  1. Use an iterator to print every second item of a list.
  2. Remove all words shorter than 4 letters from a list with an iterator.
  3. Remove all entries with a value below 50 from a map of names and marks.