What is the Iterator interface in Java, and what are its core methods?
answer
- hasNext / next / remove
- next() past end -> NoSuchElementException
- remove() is optional, acts on underlying collection
- for-each is sugar over iterator()
- Iterable gives you the Iterator
basics
~20 sIterator is an object that walks through a collection one element at a time. You call hasNext() to check if more elements remain, next() to get the next one, and remove() to delete the last element returned.
solid answer
~40 sIterator<E> is the standard Java interface for traversing a collection element by element, independent of how the collection stores its data. Its three methods are hasNext() (returns true if there are more elements), next() (returns the next element and advances the cursor), and the optional remove() (deletes the element last returned by next() from the underlying collection). Any class implementing Iterable<E> exposes an iterator via iterator(), which is what the enhanced for-each loop uses under the hood. Calling next() when hasNext() is false throws NoSuchElementException. Iterator gives a uniform traversal contract across ArrayList, HashSet, LinkedList, and more, so callers don't depend on the concrete collection type.
go deeper
Name the three methods and write the basic while(hasNext()) loop correctly, including checking hasNext() before next().
Explain Iterable vs Iterator, that for-each desugars to iterator()/hasNext()/next(), and that remove() acts on the backing collection and is optional.
Discuss the Iterator pattern's purpose (decoupling traversal from storage), the exact exception contract (NoSuchElementException, IllegalStateException, UnsupportedOperationException), and forEachRemaining.
Frame Iterator as the abstraction boundary that lets the collections framework evolve storage independently of consumers; weigh it against streams/Spliterator for parallel traversal and discuss API contract design (optional operations).
## The problem Iterator solves A **collection** is an object that holds a group of elements (a list, a set, a map's keys, etc.). Different collections store elements differently: an `ArrayList` uses a backing array, a `LinkedList` uses chained nodes, a `HashSet` uses hash buckets. If you wanted to loop over each one, you'd need to know its internal layout — array indices for one, node pointers for another. That couples your code to the implementation. The **Iterator** is the answer: a small object whose only job is to produce a collection's elements one at a time, hiding *how* they're stored. This is the classic **Iterator design pattern**: separate traversal from the container. ## The Iterable / Iterator pair Two interfaces work together: - **`Iterable<E>`** — implemented by the collection itself; it has one method, `iterator()`, which returns a fresh `Iterator<E>`. - **`Iterator<E>`** — the cursor object that actually walks the elements. Because `Collection<E>` extends `Iterable<E>`, every standard collection can hand you an iterator. ## The three methods of Iterator<E> 1. **`boolean hasNext()`** — returns `true` if calling `next()` would return an element (i.e. there is at least one more). It does *not* advance; you can call it repeatedly. 2. **`E next()`** — returns the next element and moves the internal **cursor** forward by one. If there is no next element, it throws **`NoSuchElementException`**. So the safe idiom is always: check `hasNext()` first, then call `next()`. 3. **`default void remove()`** — removes from the *underlying collection* the element that the most recent `next()` returned. It is **optional**: implementations that back an immutable or fixed view may throw `UnsupportedOperationException`. Calling `remove()` before any `next()`, or twice in a row, throws `IllegalStateException`. ## The standard loop ```java Iterator<String> it = list.iterator(); while (it.hasNext()) { String s = it.next(); // use s } ``` ## Relationship to for-each The enhanced `for (String s : list) { ... }` loop is **syntactic sugar** the compiler rewrites into exactly the `hasNext()/next()` loop above. That is why for-each works on anything `Iterable` — but it also means you cannot call `it.remove()` inside a for-each, because the iterator is hidden from you. ## Key terms recap - **Cursor**: the iterator's notion of "where am I" — conceptually a position *between* elements that advances on each `next()`. - **NoSuchElementException**: thrown by `next()` past the end. - **Optional operation**: a method the interface declares but an implementation may refuse with `UnsupportedOperationException`. Since Java 8, `Iterator` also has a default `forEachRemaining(Consumer)` that drains the rest of the elements into a lambda, but `hasNext`/`next`/`remove` remain the core contract.
- What exception does next() throw when there are no more elements?NoSuchElementException.
- Why can't you remove elements via the iterator inside a for-each loop?Because for-each hides the iterator object, so you have no reference to call remove() on; you must use an explicit Iterator loop instead.
saying these in an interview costs you the question
- Thinking remove() takes an argument (it removes the last element returned by next())
- Believing next() is safe to call without checking hasNext()
- Confusing Iterable (the collection) with Iterator (the cursor)
- Assuming you can call it.remove() inside a for-each loop