Iterators
Iterators in Java provide a standard, safe, and uniform way to traverse elements of a collection one by one. They are a fundamental part of the Java Collections Framework and are heavily tested in interviews, especially around fail-fast vs fail-safe behavior.
What Is an Iterator?
An Iterator is an object used to traverse a collection sequentially without exposing its internal structure.
- One-directional traversal
- Works with all Collection types
- Part of java.util package
Iterator<E> iterator = collection.iterator();
Why Iterators Are Needed
- Uniform traversal across collections
- Safe element removal during iteration
- Avoids index-based errors
- Supports polymorphism (List, Set, Queue)
Iterator Interface (Core Methods)
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
Basic Iterator Example
List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
✔ Sequential access
✔ Safe traversal
How Iterator Works (Execution Flow)
- iterator() creates iterator object
- hasNext() checks if element exists
- next() returns current element and moves cursor
- Loop continues until hasNext() is false
Removing Elements Using Iterator (Important)
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String val = it.next();
if (val.equals("Java")) {
it.remove(); // safe removal
}
}
✔ Safe
❌ list.remove() inside loop → ConcurrentModificationException
Iterator vs for-each Loop
| Aspect | Iterator | for-each |
|---|---|---|
| Direction | Forward only | Forward only |
| Removal | ✔ Yes | ❌ No |
| Flexibility | High | Simple |
| Internal working | Explicit | Uses Iterator internally |
Iterator vs ListIterator (Preview)
| Feature | Iterator | ListIterator |
|---|---|---|
| Direction | Forward only | Bidirectional |
| Add elements | ❌ No | ✔ Yes |
| Replace elements | ❌ No | ✔ Yes |
| Works with | All Collections | List only |
Fail-Fast Iterators (Very Important)
Most Java collection iterators are fail-fast.
What Is Fail-Fast?
- Iterator throws ConcurrentModificationException
- Occurs when collection is modified structurally during iteration
- Detects bugs early
for (String s : list) {
list.add("C++"); // ❌
}
Fail-Safe Iterators (Contrast)
- Do not throw exception
- Work on a copy of collection
- Found in concurrent collections
Examples:
- CopyOnWriteArrayList
- ConcurrentHashMap
Iterator with Set and Map
Set
Iterator<Integer> it = set.iterator();
Map (via entrySet)
Iterator<Map.Entry<Integer, String>> it =
map.entrySet().iterator();
✔ Best practice for Map iteration
Common Beginner Mistakes
- Modifying collection directly during iteration
- Forgetting hasNext() check
- Calling remove() before next()
- Using iterator incorrectly with Map
Interview-Ready Answers
Short Answer
An iterator is used to traverse elements of a collection one by one.
Detailed Answer
In Java, an Iterator provides a uniform way to traverse collections. It supports forward-only traversal and allows safe removal of elements during iteration. Most iterators are fail-fast and throw ConcurrentModificationException if the collection is modified structurally during traversal.
Iterator Examples (Quick Reference)
1. Basic Iterator with ArrayList
import java.util.*;
class Demo {
public static void main(String[] args) {
List<String> list = Arrays.asList("A", "B", "C");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
2. Iterator is One-Way (Forward Only)
import java.util.*;
class Demo {
public static void main(String[] args) {
Iterator<Integer> it = Arrays.asList(1, 2).iterator();
it.next();
// it.previous(); // ❌ Not available
}
}
Explanation: Iterator supports only forward traversal.
3. Safe Removal Using Iterator.remove()
import java.util.*;
class Demo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
if (it.next() == 2) {
it.remove();
}
}
System.out.println(list);
}
}
Output:
[1, 3]
4. ❌ Removing Without Iterator (Fail-Fast)
import java.util.*;
class Demo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
for (Integer i : list) {
// list.remove(i); // ❌ ConcurrentModificationException
}
}
}
5. Iterator with HashSet
import java.util.*;
class Demo {
public static void main(String[] args) {
Set<String> set = new HashSet<>(Arrays.asList("A", "B"));
Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
6. Iterator with Map (entrySet())
import java.util.*;
class Demo {
public static void main(String[] args) {
Map<Integer, String> map = Map.of(1, "A", 2, "B");
Iterator<Map.Entry<Integer, String>> it =
map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, String> e = it.next();
System.out.println(e.getKey() + "=" + e.getValue());
}
}
}
7. ListIterator – Forward Traversal
import java.util.*;
class Demo {
public static void main(String[] args) {
List<String> list = Arrays.asList("A", "B", "C");
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
8. ListIterator – Backward Traversal
import java.util.*;
class Demo {
public static void main(String[] args) {
List<String> list = Arrays.asList("A", "B", "C");
ListIterator<String> it = list.listIterator(list.size());
while (it.hasPrevious()) {
System.out.println(it.previous());
}
}
}
9. Modifying Elements Using ListIterator.set()
import java.util.*;
class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("Java", "API"));
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
if (it.next().equals("API")) {
it.set("Selenium");
}
}
System.out.println(list);
}
}
Output:
[Java, Selenium]
10. Adding Elements Using ListIterator.add()
import java.util.*;
class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>(Arrays.asList("A", "C"));
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
if (it.next().equals("A")) {
it.add("B");
}
}
System.out.println(list);
}
}
Output:
[A, B, C]
11. Iterator vs ListIterator
Iterator<?> it; // One direction, remove only
ListIterator<?> lit; // Two direction, add/set/remove
12. Iterator on LinkedList
import java.util.*;
class Demo {
public static void main(String[] args) {
LinkedList<Integer> list =
new LinkedList<>(Arrays.asList(1, 2, 3));
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
13. Calling remove() Before next() (Illegal)
import java.util.*;
class Demo {
public static void main(String[] args) {
Iterator<Integer> it =
Arrays.asList(1, 2).iterator();
// it.remove(); // ❌ IllegalStateException
}
}
14. Multiple remove() Calls Without next()
import java.util.*;
class Demo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2));
Iterator<Integer> it = list.iterator();
it.next();
it.remove();
// it.remove(); // ❌ IllegalStateException
}
}
15. Fail-Fast Behavior (Structural Modification)
import java.util.*;
class Demo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2));
Iterator<Integer> it = list.iterator();
list.add(3); // structural modification
// it.next(); // ❌ ConcurrentModificationException
}
}
16. Fail-Safe Example (CopyOnWriteArrayList)
import java.util.*;
import java.util.concurrent.*;
class Demo {
public static void main(String[] args) {
List<Integer> list =
new CopyOnWriteArrayList<>(Arrays.asList(1, 2));
Iterator<Integer> it = list.iterator();
list.add(3); // allowed
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
Output:
1
2
17. Iterator with TreeSet
import java.util.*;
class Demo {
public static void main(String[] args) {
Set<Integer> set = new TreeSet<>(Arrays.asList(3, 1, 2));
Iterator<Integer> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
Output:
1
2
3
18. Iterator with Queue
import java.util.*;
class Demo {
public static void main(String[] args) {
Queue<String> q = new LinkedList<>(Arrays.asList("A", "B"));
Iterator<String> it = q.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
19. Common Interview Trap
for (int i = 0; i < list.size(); i++) {
// list.remove(i); // ❌ Skips elements
}
Correct:
Iterator<?> it = list.iterator();
while (it.hasNext()) {
it.next();
it.remove();
}
20. Interview Summary – Iterators
Iterator<?> it;
Key Points
- Universal cursor for collections
- Forward-only (Iterator)
- Bidirectional (ListIterator)
- Safe removal via remove()
- Fail-fast by default
Key Takeaway
Iterators provide safe, consistent traversal across collections. Use Iterator when you need controlled iteration and safe removal.