Java for-each loops

David Y.

The Problem

The code below uses a Java for-each loop to iterate through a list:

import java.util.List; import java.util.ArrayList; class Main { public static void main(String[] args) { List<String> products = new ArrayList<>(); products.add("Coffee"); products.add("Tea"); products.add("Chocolate Bar"); for (String product : products) { System.out.println(product); } } }

What does this loop do under the hood and how could I convert my code to do the same thing using a traditional for loop?

The Solution

The for-each loop was added in Java 5 as syntactic sugar for looping through an Iterator, such as a List. The equivalent for loop looks like this:

for (Iterator<String> productIterator = products.iterator(); productIterator.hasNext(); ) { String product = productIterator.next(); System.out.println(product); }

In the for loop expression, we create a new iterator listIterator and check whether we’ve reached the final iteration with productIterator.hasNext(). Then, in the body of the for loop, we store and print the value returned by productIterator.next(). The loop will continue until productIterator.hasNext() returns false.

If we used an array instead of a List, we would need to use the following more traditional syntax instead, as an array is not an iterable:

class Main { public static void main(String[] args) { String[] products = new String[]{"Coffee", "Tea", "Chocolate Bar"}; for (int i = 0; i < products.length; i++) { String product = products[i]; System.out.println(product); } } }

In the above loops:

  • int i = 0 corresponds to Iterator<String> productIterator = products.iterator();, as both instantiate the loop.
  • i < products.length corresponds to productIterator.hasNext(), as both test whether the loop should continue or finish.
  • i++ is equivalent to productIterator.next(), as both move to the next item in the list. Even though the loop iterator is conventionally placed inside the loop expression, it can be placed inside the loop block instead with no difference in outcome.

Per the Java specification, the for-each loop will be translated to one of these loops at compilation. If the object to be looped through is an iterable (such as a List), the first loop will be used. If the object to be looped through is an array, the second loop will be used. This allows us to use the same for-each loop syntax for both arrays and iterables.

import java.util.ArrayList; import java.util.List; import java.util.Arrays; class Main { public static void main(String[] args) { List<String> productsList = new ArrayList<>(); productsList.add("Coffee"); productsList.add("Tea"); productsList.add("Chocolate Bar"); String[] productsArray = new String[]{"Coffee", "Tea", "Chocolate Bar"}; for (String product : productsList) { System.out.println(product); } for (String product : productsArray) { System.out.println(product); } // both for loops will produce the same output } }

Note that the iteration variable in a for-each loop merely contains a copy of the value at that point in the list and reassigning it will not change the underlying list. For example:

String[] products = new String[]{"Coffee", "Tea", "Chocolate Bar"}; for (String product : products) { if (product == "Chocolate Bar") { product = "Granola Bar"; } } System.out.println(Arrays.toString(products)); // will print ["Coffee", "Tea", "Chocolate Bar"]

Loved by over 4 million developers and more than 90,000 organizations worldwide, Sentry provides code-level observability to many of the world’s best-known companies like Disney, Peloton, Cloudflare, Eventbrite, Slack, Supercell, and Rockstar Games. Each month we process billions of exceptions from the most popular products on the internet.

Share on Twitter
Bookmark this page
Ask a questionJoin the discussion

Related Answers

A better experience for your users. An easier life for your developers.

    TwitterGitHubDribbbleLinkedinDiscord
© 2024 • Sentry is a registered Trademark
of Functional Software, Inc.