The for-each statement

Lesson content

  • What is a for-each loop – declaration and elements
  • Nesting statements inside a for-each loop
  • The break, return, and continue statements
  • Infinite and non-executable for-each loops
  • When to use for-each and when to use other types of loops
  • Most common errors

What is a for-each loop – declaration and elements

The for-each loop is designed to make working with data structures simpler, particularly arrays and lists.

When performing operations on arrays, it is common to use a for loop where the loop counter iterates over array indices (from 0 to length - 1), since all elements of the array are typically processed. This results in code that is nearly identical in every array-handling algorithm. For example, to print all elements of an array, the following loop is used:

1 for (int i = 0; i < array.length; i++)
2     System.out.println(array[i]);

In this approach, each array element is accessed by its index, one by one from the first to the last (array[i]). Based on this repetitive pattern, the for-each loop was introduced to provide the same functionality with simpler syntax and without using indices directly.

In literature, the for-each loop is often referred to as the “enhanced for loop”.

Here is a for-each loop that does the same as the previous for loop:

1 for (int element : array)
2     System.out.println(element);

You can notice that the declaration also starts with the reserved word for, but inside the parentheses, something different appears. It contains the declaration of a helper variable into which the values of array elements will be copied (int element), followed by a colon (‘:’) and the name of the array to be traversed.

In each iteration, the for-each statement takes one array element and copies its value into the helper variable element. In the first iteration, the value of the first array element will be in element, then the second element in the second iteration, and so on until the last. Therefore, when printing, the helper variable element is used instead of referencing the array directly.

Unlike other loops, the exit condition for a for-each loop is not explicitly stated — the number of iterations is equal to the number of elements in the array, unless execution is altered using continue, break, or return.

While for, while, and do-while loops can be used in all scenarios where code needs to repeat, the for-each loop is used only with arrays, lists, or other data structures that have an iterator (the iterator concept is covered in the lesson on lists in Java).

Thus, the for-each loop cannot be used unless you’re working with an array, list, or similar structure.

In addition, the for-each loop has some important limitations:

  • You cannot modify the contents of the array/list, since you’re working with element copies via the helper variable. You can’t insert, delete, change values, or rearrange elements.
  • You cannot skip elements during iteration (e.g., process every fifth element). You can only interrupt a current iteration using continue.
  • You cannot iterate in reverse order (from the end to the beginning).
  • You cannot traverse multiple arrays/lists simultaneously within a single loop.
  • You cannot create a “nested” for-each loop that goes through the same array or list in a multi-level manner.

The general syntax of a for-each loop is shown below. The helper variable must match the type of the array/list elements, since it holds a copy of their value:

1 for (ElementType helperVariable : array)
2     command;

When this for-each loop is run, the sequence of execution is as follows:

 1 START OF LOOP
 2 1st ITERATION
 3    Helper variable gets a copy of the first array element
 4    command is executed
 5 2nd ITERATION
 6    Helper variable gets a copy of the second array element
 7    command is executed
 8 3rd ITERATION
 9    Helper variable gets a copy of the third array element
10    command is executed
11 ...
12 LAST ITERATION
13    Helper variable gets a copy of the last array element
14    command is executed
15 END OF LOOP

As with all other loops, if multiple commands need to be repeated in each iteration, they must be enclosed in a code block using curly braces:

1 for (ElementType helperVariable : array) {
2     command_1;
3     command_2;
4     ...
5     command_n;
6 }

Example 1

Let’s take the example of the MonthlyProfits class from a previous lesson. Let’s now write an alternative version of this class named MonthlyProfits2, using the for-each loop where applicable. The class should look like this:

  • An attribute profits that represents an array of 12 real numbers. Each element of the array represents the profit for a specific month (January, February, …, December).

  • A no-argument constructor that initializes the profits array with a capacity of 12.

  • A method enterProfit that takes a real number representing the profit and an integer representing the month’s order (1 - January, 2 - February, …, 12 - December). The method enters the appropriate profit value into the array for that month.

  • A method print that prints the profits for all months to the screen.

  • A method sum that sums up the profits for all 12 months and prints the total annual profit on the screen.

 1     class MonthlyProfits2 {
 2 
 3         double[] profits;
 4 
 5         MonthlyProfits2(){
 6             profits = new double[12];
 7         }
 8 
 9         void enterProfit(double profit, int month){
10             profits[month -1] = profit;
11         }
12 
13         void print(){
14             for(double profit: profits)
15                 System.out.println(profit);
16         }
17 
18         void sum(){
19             double totalProfit = 0;
20 
21             for(double profit: profits)
22                 totalProfit = totalProfit + profit;
23 
24             System.out.println("Total profit is: " + totalProfit);
25         }
26     }

Create a class TestMonthlyProfits2 where in the main method you:

  • Create an object of the MonthlyProfits2 class.
  • Enter the profit for February as 122.33 and May as 255.44.
  • Print all monthly profits to the screen, and then the total annual profit.
 1     class TestMonthlyProfits2 {
 2 
 3         public static void main(String[] args) {
 4             MonthlyProfits2 mp = new MonthlyProfits2();
 5 
 6             mp.enterProfit(122.33, 2);
 7 
 8             mp.enterProfit(255.44, 5);
 9 
10             mp.print();
11 
12             mp.sum();
13         }
14     }

You can see that the constructor and enterProfit method remain unchanged. If we needed to initialize the array elements in the constructor to some default value (e.g., -1), that would not be possible using a for-each loop. It would have to be done with a for or another loop type. As mentioned, the for-each loop works with copies of array elements, so any changes affect only the copy, not the actual array.

The for-each loop can be used in the print and sum methods because:

  • There is no modification of the array elements.
  • It iterates through all array elements in order, from index 0 to length - 1.

From the code in these two methods, you can see that a helper variable of type double, named profit, is used to iterate through the profits array. In each iteration, the helper variable holds a copy of one array element. That value is then either printed (print method) or added to the total profit (sum method).

Nesting statements inside a for-each loop

As with other control statements (IF, SWITCH, FOR, WHILE, DO-WHILE), the for-each loop can be combined (nested) with all other flow control statements.

This means you can nest an if or switch inside the block of a for-each loop — or vice versa, nest a for-each (or any other loop) inside an if or switch block.

However, as previously noted, you cannot create a “double” or nested for-each loop that iterates over the same array or list.

Example 2

Let’s take the example of the ExamGrades class from a previous lesson. Now we’ll create an alternative version called ExamGrades2A using the for-each loop where appropriate. This class should contain:

  • An attribute examName representing the name of the exam.

  • An attribute grades representing the student grades from that exam. A grade is an integer from 5 to 10.

  • A constructor that takes the number of students who registered for the exam and initializes the capacity of the grades array to that number.

  • A method enterGrade that takes a grade as a parameter and inserts it into the first available position in the array.

  • A method print that prints all data about the exam: the exam name and all grades.

  • A method printPassCount that counts and prints how many students passed the exam (i.e., received a grade higher than 5).

 1     class ExamGrades2A {
 2 
 3         String examName;
 4 
 5         int[] grades;
 6 
 7         ExamGrades2A(int totalStudents){
 8             grades = new int[totalStudents];
 9         }
10 
11         void enterGrade(int grade){
12             // here you can't use the for-each loop
13             // because new values need to be entered in the array
14             for (int i = 0; i < grades.length; i++)
15                 if (grades[i] == 0){
16                     grades[i] = grade;
17                     return;
18                 }
19 
20             System.out.println("No more room for new grades");
21         }
22 
23         void print(){
24             System.out.println("Exam name: " + examName);
25 
26             System.out.println("Grades: ");
27             // All grades from the array that are different from 0
28             // are printer. Zeroes represent "free spots" - array
29             // elements in which the grade is not yet entered
30             // so they don't need to be printed.
31             for(int grade : grades)
32                 if (grade != 0)
33                     System.out.println(grade);
34         }
35 
36         void printPassRate(){
37             // Helper variable that serves as counter for
38             // students who have passed the exam. The
39             // initial value is 0.
40             int passed = 0;
41 
42             // Passes through all array elements and checks if
43             // the current array element (grade)is greater than 5.
44             // If it is, the number of students who have passed
45             // the exam increases by one.
46             for(int grade : grades)
47                 if (grade > 5)
48                     passed++;
49 
50             System.out.println("The number of students that have passed is: " + passed);
51         }
52     }

Create a class TestExamGrades2A where the main method:

  • Creates an object of the ExamGrades2A class with 12 registered students
  • Sets the exam name to “Java Programming”
  • Enters the grades 5, 10, 10, 7, and 8
  • Prints all exam data to the screen
  • Prints the pass count — how many students passed the exam
 1     class TestExamGrades2A {
 2 
 3         public static void main(String[] args) {
 4             ExamGrades2A eg = new ExamGrades2A(12);
 5 
 6             eg.examName = "Java programming";
 7 
 8             eg.enterGrade(5);
 9             eg.enterGrade(10);
10             eg.enterGrade(10);
11             eg.enterGrade(7);
12             eg.enterGrade(8);
13 
14             eg.print();
15 
16             eg.printPassRate();
17         }
18     }

In this example as well, the constructor remains unchanged, and the same goes for the enterGrade method. This is because in that method, values are being entered into the array, meaning the contents are being modified — which cannot be done using a for-each loop. Therefore, a regular for loop is used.

On the other hand, the print method can use a for-each loop because it simply reads and prints values. This example also shows how an if statement can be nested inside a for-each loop, allowing it to skip grades that are zero (zero represents an empty/unset spot in the array).

Similarly, the printPassCount method uses a for-each loop to go through the entire grades array and count how many grades are greater than 5. This is done by nesting an if statement within the for-each loop. The result is the total number of students who passed the exam.

Note: In the previous lesson, there’s an improved version of this class called ExamGrades2, which introduces a counter to keep track of the number of entered grades. In that version, the for-each loop cannot be used in the same way, because it always iterates through the entire array (from 0 to length - 1) and there’s no easy way to restrict it to just the entered grades (from 0 to counter - 1).

The break, return, and continue statements

The usual way to exit a for-each loop is by going through all the elements of the array or list. In other words, the expected number of iterations is always equal to the number of elements in the array or list.

On the other hand, the statements return, break, and continue work the same way across all loops in Java, including for-each, and can be used to:

  • Interrupt a single iteration (continue)
  • Exit the loop early (break)
  • Exit the entire method (return)

The details of how these three statements work are covered in the lesson on the for loop. Their effects on loop execution (for any loop type, not just for-each) are summarized in the table below:

Command Effect on loop execution
continue Only the current iteration is interrupted, the loop and method continue
break The loop is interrupted, the method continues
return Everything is interrupted: both the loop and the entire method

Infinite and non-executable for-each loops

Unlike other loop types, a for-each loop cannot be written as an infinite loop.

The reason is that the number of iterations always matches the number of elements in the array or list, and this cannot be altered.

Similarly, a for-each loop can be a non-executable loop only if the array or list contains no elements.

For arrays, this means that the array was not initialized, or it was initialized with a capacity of zero (which is technically allowed).

When to use for-each and when to use other types of loops

As already mentioned, in Java, any for loop can be rewritten as a while or do-while loop, and vice versa. In doing so, you get similar or identical compiled (machine-level) code, so from a performance standpoint, it makes no difference which loop you use in your source code.

The only real difference is in code readability — for example, sometimes code is more readable when written with a for loop instead of a while loop, or the other way around.

However, the for-each loop is very specific, as it works only with data structures (like arrays and lists), and it has two key limitations:

  • You cannot modify the values of elements (nor their order).
  • You must iterate through the entire array/list from start to end (you cannot skip elements, etc.).

Therefore, we can say that every for-each loop can be rewritten as a for, while, or do-while loop, but the reverse is not always true.

When should each type of loop be used for better code readability?

  • for loop:

    • When the number of iterations is known in advance.
    • When it makes sense to use a loop counter (iteration index).
    • When working with arrays of data (covered in the lesson on arrays).
  • while and do-while loops:

    • When the number of iterations is not known in advance (e.g., waiting for a certain condition like end-of-file).
    • When it doesn’t make sense to introduce a loop counter.
    • When a counter is needed, but it’s not counting iterations of the loop (e.g., a helper counter). This helper counter often doesn’t participate in the loop condition and may need to be initialized and used outside the loop as well.
  • for-each loop (with the mentioned limitations):

    • When working with data structures like arrays or lists.
    • When the values or the order of elements do not need to be changed.

Most common errors

Some of the most common syntax errors related to writing the FOR-EACH loop are:

  • Using an incorrect type for the auxiliary variable that does not match the type of the elements in the array or list. For example, a double auxiliary variable can be used for an array of integers, but other combinations are not allowed, e.g.:
1     int[] array = new int[10];
2   
3     for (boolean element : array)
4         System.out.println(element);

Instead (correct code):

1     int[] array = new int[10];
2   
3     for (int element : array)
4         System.out.println(element);
  • Referring to a variable that is not a data structure or does not have an iterator (array, list, etc.):
1     double profit = 123.22;
2   
3     for (double element : profit)
4         System.out.println(element);

Instead (correct code):

1     double[] profit = {123.22, 43423.01, 4397.55};
2   
3     for (double element : profit)
4         System.out.println(element);

Other common mistakes that are not syntax errors, but affect the program’s behavior, include:

  • Writing a FOR-EACH loop in situations where you need to modify the values of array elements. In these cases, no syntax error will occur, but the effect of execution will be as if nothing happened (the array elements won’t be modified), e.g.:
 1       int[] grades;
 2    
 3       void enterGrade(int grade) {
 4           for (int g : grades)
 5               if (g == 0) {
 6                   g = grade;
 7                   return;
 8               }
 9     
10           System.out.println("No more space in the array for new grades");
11       }

Instead (correct code):

 1     int[] grades;
 2   
 3     void enterGrade(int grade) {
 4         for (int i = 0; i < grades.length; i++)
 5             if (grades[i] == 0) {
 6                 grades[i] = grade;
 7                 return;
 8             }
 9   
10         System.out.println("No more space in the array for new grades");
11     }