Iterators in Java
Traverse collections using Iterator and ListIterator, implement the Iterable interface on custom classes, and understand the for-each contract.
Why Iterators Matter
1. What is an Iterator?
An `Iterator` is an object that traverses a collection one element at a time without exposing the underlying structure. It answers three questions: does a next element exist (`hasNext`), give me the next element (`next`), and optionally remove it (`remove`).
The Iteration Protocol
1. Iterator Interface
The `Iterator<T>` interface has two key methods: `hasNext()` — returns true if more elements exist, and `next()` — returns the next element and advances the cursor.
2. Built-in Iterables
All standard Java collections — `List`, `Set`, `Map.entrySet()`, arrays via `Arrays.asList()` — implement `Iterable` and support `iterator()` and for-each.
Removing Elements While Iterating
1. Safe Removal Using Iterator
Never use `list.remove()` inside a for-each loop — it throws `ConcurrentModificationException`. Use `iterator.remove()` instead.
ListIterator
1. Bidirectional Traversal & Modification
`ListIterator` extends `Iterator` with `hasPrevious()`, `previous()`, `set()`, and `add()`. It works only on `List`, not `Set` or `Map`.
Creating a Custom Iterable
1. Custom Iterator Object
Implement `Iterable<T>` on your class and return an `Iterator<T>` from `iterator()`. This lets your class work in for-each loops.
Lazy Evaluation
1. Infinite Sequence with Stream.iterate
`Stream.iterate()` and `Stream.generate()` create potentially infinite sequences — values are produced only when consumed.
Backend Use Cases
1. Batch Processing
Process large datasets in fixed-size chunks to avoid loading everything into memory at once.
Pitfalls & Best Practices
1. Recommended Guidelines
Practical rules for writing safe, idiomatic iteration code in Java.