Unravel โบ Java concepts โบ Collections and streams
Iterator and Iterable
An Iterator walks through a collection one element at a time (hasNext, next, remove).
Learn these first
At a glance
A bookmark in a book: it knows where you are, can tell you whether there is another page, and moves forward one page at a time without you caring how the book is bound.
- 1for (String s : list) is shorthand for getting list.iterator() and looping while (it.hasNext()) { String s = it.next(); ..}.
- 2To remove while looping, use the iterator itself: it.remove() after next()Removing through the collection during a for-each throws ConcurrentModificationException.
- 3To make your own class work in for-each, implement Iterable<T> and return an Iterator<T> from iterator()
- 4ListIterator can also go backwards and replace elements
- Iterators of the standard collections are fail-fast: they check a modification counter and throw as soon as they notice a change they did not make
- Iterators of concurrent collections are weakly consistent: they never throw, and may or may not show changes made after they were created
- ArrayList.Itr stores a cursor, lastRet and an expectedModCount that it compares with the list's modCount on every next() and remove()
import java.util.*;public class Range implements Iterable<Integer> { private final int from, to; Range(int from, int to) { this.from = from; this.to = to; } @Override public Iterator<Integer> iterator() { return new Iterator<>() { int next = from; public boolean hasNext() { return next < to; } public Integer next() { return next++; } }; } static void dropNegatives(List<Integer> list) { for (Iterator<Integer> it = list.iterator(); it.hasNext(); ) if (it.next() < 0) it.remove(); }}- line 2 uses Iterable, the core of Iterator and Iterable
- line 5 uses Iterator, the core of Iterator and Iterable
- line 6 uses Iterator, the core of Iterator and Iterable
- line 8 uses hasNext, the core of Iterator and Iterable
- line 13 uses Iterator, the core of Iterator and Iterable
Read the full explanation (about 1 min)
An Iterator walks through a collection one element at a time (hasNext, next, remove). Anything implementing Iterable can be used in a for-each loop.
A mental model
A bookmark in a book: it knows where you are, can tell you whether there is another page, and moves forward one page at a time without you caring how the book is bound.
How it works
for (String s : list) is shorthand for getting list.iterator() and looping while (it.hasNext()) { String s = it.next(); ... }.
To remove while looping, use the iterator itself: it.remove() after next(). Removing through the collection during a for-each throws ConcurrentModificationException.
To make your own class work in for-each, implement Iterable<T> and return an Iterator<T> from iterator().
ListIterator can also go backwards and replace elements.
Going deeper
Iterators of the standard collections are fail-fast: they check a modification counter and throw as soon as they notice a change they did not make. This is a best-effort bug detector, not a guarantee for threads.
Iterators of concurrent collections are weakly consistent: they never throw, and may or may not show changes made after they were created.
Lazy iterators (read a file or database cursor line by line) need closing; wrap them in a Stream with onClose or in try-with-resources.
Under the hood
ArrayList.Itr stores a cursor, lastRet and an expectedModCount that it compares with the list's modCount on every next() and remove().
Common mistakes
- Calling
it.remove()beforenext(). - Removing from the list inside for-each.
- Calling
next()withouthasNext().
How Unravel recognises it
When you paste code, Unravel looks for these signs of iterator and iterable. Spotting them yourself is a good habit when you read unfamiliar code:
- Types:
IteratorListIteratorIterableSpliterator - Method calls:
iterator()hasNext()listIterator()
Part of a learning path
- Collections in depth ยท previous: PriorityQueue and heaps ยท next: ConcurrentModificationException
Related concepts
Frequently asked questions
What is Iterator and Iterable?
An Iterator walks through a collection one element at a time (hasNext, next, remove). Anything implementing Iterable can be used in a for-each loop.
What are the most common mistakes with Iterator and Iterable?
Calling it.remove() before next(). Removing from the list inside for-each. Calling next() without hasNext().
How can I see Iterator and Iterable in real code?
Paste your own Java into Unravel and it will point out where iterator and iterable appears, explain how it works at the detail level you choose, and draw the flow of the code around it.