How does the Java 'for each' loop work?
A Java 'for each' loop is a handy way to iterate over elements in arrays and Iterable
collections. The use of an internal Iterator eliminates explicit index tracking, resulting in cleaner code:
Here, item
is assigned each value from the list successively, making it straightforward to access elements without the potential error-prone manual index handling.
Diving into Further Details
Cracking the Underlying Mechanism
In a for each
loop, Java covertly uses an Iterator to traverse the collection. Suppose we perform the looping manually using an Iterator
. In that case, it will look something like:
Knowing that Iterator
underlies the for each
loop, it becomes clear why this loop type can only go over Iterable
objects. It also helps explain why certain modifications (such as removal of elements during iteration) aren't permitted, as they can lead to well-known errors like ConcurrentModificationException
.
Amending Entries, Safe and Permissible
for each
loops don't inherently support the removal of elements. To do that safely, you'll need to use an Iterator
directly:
This way, you're in full control of collection amendments, avoiding the hassles of index-based element removal.
Array vs Iterable Speed
When operating on primitive arrays, a conventional for
loop is lightning-fast due to direct index access:
However, with Iterable
objects (like List<Integer>
), a for each
loop is more efficient than an indexed loop due to the boxing and unboxing overhead with the Integer
type.
Efficiency with Index-based Collections
For collections that offer efficient indexed access (like ArrayList
), both classic for
loops and Iterator
can perform similarly. Choosing the right tool for the task is crucial — random access is effective for indexed collections, whereas for each
shines when indices aren't a concern, or when traversing collections with inefficient index-based access.
Custom Class Adventures in 'for each' Land
Implementing Iterable
Making your custom classes Iterable
equips them with for each
loop compatibility, improving their flexibility, and congruity with the Java collection framework:
Once Iterable
is implemented, vanquishing the complexity of iterating over your custom collection with a for each
loop becomes a piece of cake.
The Iteration Barometer
Choosing the Right Iteration Method
The iteration method of choice boils down to the use case: indexed for
loops for precision and speed with arrays, for each
for ease of use and safety with Iterable
collections, and explicit Iterator
usage when modifications are needed. It's a delicate dance between manipulation needs and performance considerations.
Visualising the 'for each' Loop
You're the conductor of a train(🚂), checking every carriage:
Java Collection : [Carriage 🍎, Carriage 🍌, Carriage 🍒]
Appropriate 'for-each' code:
for (Fruit carriage : fruitTrain) {
// Conductor inspecting each carriage (🍎, then 🍌, then 🍒)
}
Just like the conductor, the loop proceeds to the next carriage (element) using the train's (collection's) tracks (Iterator), making for a smooth, index-free ride!
Advancing Your Iteration Game
Scaring the 'ConcurrentModificationException' Ghost Away
Understanding Java's 'for each' loop entails acknowledging its limitations, especially related to concurrency. Using for each
while modifying the collection (like adding or removing elements) can trigger ConcurrentModificationException
. To exorcise this ghost, use the Iterator
with the remove()
method.
Custom Iteration Actions
When your iteration actions need to veer off the beaten path, or when additional operations during iteration are called for, then directly using Iterable
interface and Iterator
methods becomes the go-to approach.
Mastering Iterable
Diving into the Iterable
interface is the prime step toward understanding for each
loops. This knowledge prepares you to pick the right loop for the task—whether it's the simplicity of for each
, the control of an explicit Iterator
, or the precision of an indexed loop.
Was this article helpful?