Iterators & Callbacks
1054 words
5 min read
Visual companion
Python
Type and operator map
Python Week 1: the first filter for runtime behavior
View
Revision summary
What this note is really saying
Short form
# Iterators & Callbacks ## 🎯 Learning Objectives - Implement the `Iterable` and `Iterator` interfaces - Use enhanced for-each loops with custom collections - Understand the callback pattern using interfaces - Use anonymous inner classes and lambda expressions (preview) ## 1. Iterators — How For-Each Really Works ##...

Iterators & Callbacks
🎯 Learning Objectives
- Implement the
IterableandIteratorinterfaces - Use enhanced for-each loops with custom collections
- Understand the callback pattern using interfaces
- Use anonymous inner classes and lambda expressions (preview)
1. Iterators — How For-Each Really Works
1.1 The Iterable and Iterator Interfaces
java// java.lang.Iterable<T> — what enables the for-each loop public interface Iterable<T> { Iterator<T> iterator(); } // java.util.Iterator<T> — the actual traversal public interface Iterator<E> { boolean hasNext(); // Is there a next element? E next(); // Return next element and advance default void remove() { throw new UnsupportedOperationException(); } }
1.2 Custom Iterable Collection
javapublic class Range implements Iterable<Integer> { private int start, end; public Range(int start, int end) { this.start = start; this.end = end; } @Override public Iterator<Integer> iterator() { return new RangeIterator(); } // Private inner class implements Iterator private class RangeIterator implements Iterator<Integer> { private int current = start; @Override public boolean hasNext() { return current < end; } @Override public Integer next() { if (!hasNext()) throw new NoSuchElementException(); return current++; } } } // Usage: Range range = new Range(1, 5); for (int n : range) { // Works because Range implements Iterable System.out.print(n + " "); } // Output: 1 2 3 4
1.3 How For-Each is Translated
java// This code: for (String s : list) { System.out.println(s); } // Is compiled to this: Iterator<String> iter = list.iterator(); while (iter.hasNext()) { String s = iter.next(); System.out.println(s); }
1.4 Fail-Fast Iterators
Most collection iterators are fail-fast: if the collection is structurally modified after the iterator is created (except through the iterator's own
remove), the iterator throws ConcurrentModificationException.javaList<String> list = new ArrayList<>(Arrays.asList("A", "B", "C")); for (String s : list) { if (s.equals("B")) { list.remove(s); // Throws ConcurrentModificationException! } }
2. Callbacks — Interfaces as Function Parameters
2.1 The Problem
How do you pass behavior to a method in Java? In Python, you can pass a function directly. In Java (pre-lambdas), you pass an object whose interface defines the behavior.
2.2 Callback via Interface
java// Define the callback interface public interface ClickListener { void onClick(Button source); } // The framework accepts callbacks public class Button { private ClickListener listener; public void setOnClick(ClickListener listener) { this.listener = listener; } public void click() { if (listener != null) { listener.onClick(this); } } } // Client code Button btn = new Button(); btn.setOnClick(new ClickListener() { // Anonymous inner class @Override public void onClick(Button source) { System.out.println("Button clicked!"); } });
2.3 Anonymous Inner Classes
An anonymous inner class is a class without a name, defined and instantiated in one expression:
java// Syntax: new Interface/Class() { method implementations } Comparator<String> byLength = new Comparator<String>() { @Override public int compare(String a, String b) { return Integer.compare(a.length(), b.length()); } };
Limitations:
- Cannot define a constructor
- Can only extend one class or implement one interface
- Must override all abstract methods
2.4 Lambda Expressions (Java 8+ Preview)
java// Lambda replaces anonymous inner class for functional interfaces Comparator<String> byLength = (a, b) -> Integer.compare(a.length(), b.length()); // Even shorter: Comparator<String> byLength = Comparator.comparingInt(String::length);
A functional interface is an interface with exactly one abstract method (like
Comparable, Runnable, Comparator). Lambdas work only with functional interfaces.3. Common Pitfalls
Pitfall 1: Concurrent Modification During Iteration
javafor (String s : list) { list.remove(s); } // ConcurrentModificationException!
Fix: Use
iterator.remove() or collect items to remove and do it after.Pitfall 2: Iterator's next() Without hasNext() Check
javaIterator<String> it = list.iterator(); String s = it.next(); // NoSuchElementException if list is empty
Pitfall 3: Forgetting to Declare Iterator as Inner Class
The iterator often needs access to the outer object's state. Using a private inner class (or anonymous class) is the standard pattern.
4. Practice Questions
Q1: What does Iterable provide?Answer: Theiterator()method, which returns anIterator<T>. ImplementingIterableenables the for-each loop. Q2: What is the output?javaList<String> list = new ArrayList<>(Arrays.asList("A", "B", "C")); Iterator<String> it = list.iterator(); it.next(); it.remove(); System.out.println(list);Answer:[B, C]—remove()removes the element returned by the lastnext()call. Q3: Why can't you modify a collection during for-each iteration?Answer: For-each internally uses an iterator. The collection tracks structural modifications via a modCount field. If the modCount changes during iteration (not via the iterator's own methods), the iterator detects this and throwsConcurrentModificationExceptionto prevent undefined behavior. Q4: What is a functional interface?Answer: An interface with exactly one abstract method. Examples:Runnable,Callable,Comparator,ActionListener. These can be implemented with lambda expressions. Q5: What are the limitations of anonymous inner classes?Answer: No constructor, can only extend one class or implement one interface, verbose syntax, and can't be reused. Q6: Implement an Iterable that returns even numbers up to a limit.javapublic class EvenNumbers implements Iterable<Integer> { private int limit; public EvenNumbers(int limit) { this.limit = limit; } @Override public Iterator<Integer> iterator() { return new Iterator<Integer>() { int current = 0; @Override public boolean hasNext() { return current <= limit; } @Override public Integer next() { int val = current; current += 2; return val; } }; } }Q7: How does the callback pattern enable Swing event handling?Answer: Swing components accept callback objects (listeners) that implement interfaces likeActionListener. When an event occurs (button click), Swing calls the listener's method. This decouples the UI framework from application logic. Q8: Can you use a lambda for any interface?Answer: No. Lambda expressions can only be used for functional interfaces (interfaces with a single abstract method). For interfaces with multiple abstract methods, use anonymous inner classes.
📐 Key Concepts
| Interface | Method | Purpose |
|---|---|---|
Iterable | iterator() | Enables for-each |
Iterator | hasNext(), next(), remove() | Traversal |
| Functional interface | 1 abstract method | Lambda-compatible |
| Callback | Interface passed to method | Behavior injection |
🔗 Cross-References
- Next: Generics
- Related: Streams API & Lambdas Join Discord Previous5.1 Packages & Access ModifiersNext6.1 Generics