What are the Iterator and Iterable interfaces in Java, and how do they relate to each other and to the Iterator design pattern?
answer
- Iterable = factory (iterator()); Iterator = the cursor
- hasNext / next / remove
- for-each is sugar over iterator()
- next() advances and can throw NoSuchElementException
- GoF Iterator pattern: traverse without exposing internals
basics
~20 sIterable means 'can be looped over' — it has one method, iterator(), that hands you an Iterator. The Iterator does the actual walking with hasNext() and next(). The for-each loop uses both behind the scenes.
solid answer
~40 sIterable<T> is the 'I can be traversed' contract: its single method iterator() returns a fresh Iterator<T>. Iterator<T> is the cursor that does the walking — hasNext() reports whether more elements remain, next() returns the next one and advances, and the default remove() optionally deletes the last-returned element. Collections like ArrayList implement Iterable, so they can produce iterators. This is the Gang-of-Four Iterator pattern: it lets a client traverse a collection sequentially without knowing its internal structure (array, linked nodes, tree). The for-each loop (for (T x : items)) is pure syntactic sugar that calls iterator() once, then loops on hasNext()/next(). Splitting the two interfaces means one collection can hand out many independent iterators, each with its own position.
code
java · 13 linesList<String> names = List.of("ann", "bob", "cy");
// for-each (sugar)
for (String n : names) {
System.out.println(n);
}
// the desugared equivalent
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String n = it.next(); // returns current, then advances
System.out.println(n);
}go deeper
Knows for-each loops over collections and can name hasNext()/next(); understands Iterable is what makes for-each work.
Explains the Iterable-as-factory / Iterator-as-cursor split, that each iterator() call is independent, and how for-each desugars.
Frames it as the GoF Iterator pattern (decoupling traversal from structure), discusses remove()/forEachRemaining defaults, and notes arrays are handled separately by the compiler.
Can reason about designing an Iterable abstraction for a custom data structure or lazy source, weighing iterator independence, statefulness, and the contract guarantees clients may rely on.
## The problem the Iterator pattern solves A **collection** is any object that holds a group of elements — a list, a set, a map's keys, etc. Different collections store their elements very differently: an `ArrayList` uses a backing array, a `LinkedList` uses chained nodes, a `TreeSet` uses a balanced tree. A client that wants to visit every element ('traverse' the collection) should not have to know or care about that internal layout. The **Iterator design pattern** (one of the classic Gang-of-Four behavioural patterns) solves this by providing a separate **cursor object** that knows how to walk one specific collection and exposes a tiny, uniform interface to the outside world. ## The two Java interfaces Java encodes this pattern with two interfaces in `java.util` / `java.lang`: **`Iterable<T>`** (in `java.lang`) means 'this object can be iterated over'. It has exactly one abstract method: ```java Iterator<T> iterator(); ``` Calling `iterator()` produces a brand-new cursor positioned before the first element. `T` is a **generic type parameter** — a placeholder for the element type, so `Iterable<String>` yields an `Iterator<String>`. **`Iterator<T>`** (in `java.util`) is the cursor itself. Its core methods: - `boolean hasNext()` — returns `true` if there is at least one more element to visit. It does **not** move the cursor. - `T next()` — returns the next element **and** advances the cursor past it. If there is no next element it throws `NoSuchElementException`. - `default void remove()` — removes from the underlying collection the element that `next()` last returned. It is a *default* method that throws `UnsupportedOperationException` unless the concrete iterator overrides it; it is the only safe way to delete during iteration. - `default void forEachRemaining(Consumer<? super T> action)` — runs an action over every element still left. ## How the two fit together `Iterable` is the **factory**; `Iterator` is the **product**. A collection class (e.g. `ArrayList`) implements `Iterable` and, inside `iterator()`, returns an instance of a (usually private, inner) class that implements `Iterator` and holds the traversal state — typically an index or a node pointer. Because each call to `iterator()` creates a fresh cursor, you can have several iterators walking the same collection at once, each at its own position. In Gang-of-Four terms: the collection is the *Aggregate*, `iterator()` is the *createIterator* factory method, and the returned cursor is the *ConcreteIterator*. ## The for-each connection The enhanced for loop is built directly on `Iterable`: ```java for (String s : list) { use(s); } ``` is compiled to roughly: ```java for (Iterator<String> it = list.iterator(); it.hasNext(); ) { String s = it.next(); use(s); } ``` So any object whose type implements `Iterable` works in a for-each loop — that is the entire requirement. Arrays are a special case the compiler handles separately (they are not `Iterable`). ## Why separate the two interfaces? Separating 'can be traversed' (`Iterable`) from 'the live cursor with position state' (`Iterator`) keeps the collection stateless with respect to traversal and lets multiple independent walks proceed simultaneously. It also lets non-collection things (a stream of lines from a file, a range generator) be `Iterable` without being storage at all.
- Can you call next() without ever calling hasNext()?Yes — hasNext() is not mandatory, it is just a guard. But if you call next() when no element remains, it throws NoSuchElementException, so checking hasNext() first is the safe idiom.
- Does iterator() return the same iterator each time?No. Each call returns a new, independent cursor positioned at the start, so multiple iterations can run concurrently without interfering.
Iterable is a library that issues you a bookmark; the Iterator is the bookmark itself, tracking exactly where you are. The library can issue many bookmarks at once, each in a different spot.
saying these in an interview costs you the question
- Saying hasNext() advances the cursor — it does not; only next() moves it
- Thinking arrays are Iterable (they work in for-each via special compiler support, but do not implement Iterable)
- Confusing Iterator and Iterable, or claiming for-each calls next() without first obtaining an iterator()