ForEach Loop in Java (original) (raw)

The **for-each loop in Java (also called the enhanced for loop) was introduced in Java 5 to simplify iteration over arrays and collections. It is cleaner and more readable than the traditional for loop and is commonly used when the exact index of an element is not required.

**Example: Using a for-each loop to print each element of an array in Java.

Java `

// Java Program to Iterate through an array // Using for-each loop import java.io.*;

class Geeks {

public static void main(String[] args) {
  
    // Array declaration
    int arr[] = { 1, 2, 3, 4, 5 };
    
    // Using for-each loop to 
    // print each element
    for (int e : arr) {
        System.out.print(e + " ");
    }
}

}

`

**Explanation: In this example, the for-each loop iterates over the array “arr" and prints each element. We use the variable element "e" to access each value in the array, making the loop more concise compared to using a traditional for loop with an index.

Syntax of For-each Loop

for (type var : array) {

statements using var;

}

**Parameters:

**When to Use For-Each Loop?

Use for-each loop when:

**When to Avoid For-Each Loop?

Avoid using for-each loop when:

Finding Maximum in an Array using for-each Loop

**Example: This example demonstrates howto find the maximum value in an integer array using a for-each loop.

Java `

// Java Program to find maximum in an array // Using for-each loop public class Geeks {

public static void main(String[] args) {
  
    int[] mark = {125, 132, 95, 116, 110};

    int max = findMax(mark);
    System.out.println("" + max);
}

public static int findMax(int[] n) {
    int maximum = n[0];

    // Iterates through the array
    for (int n1: n) {        
        if (n1 > maximum) {
            maximum = n1;
        }
    }
    return maximum;
}

}

`

**Explanation: In the above example, we create a method **findMax(). This method takes an array and then we assume the first element as mas and then use the **for-each to iterate each element of the array and compare it with the max, if it is greater than the max then update the max value.

Iterating in a List using for-each loop

**Example: This example demonstrates how to **find the maximum element in a list using a for-each loop.

Java `

// Java program to iterate through a list of Integers // using for-each loop and find the maximum element import java.util.ArrayList; import java.util.Arrays; import java.util.List;

class Geeks { public static void main(String[] args) {

   // List of Integers
   List<Integer> l = new ArrayList<>();
   l.add(3);
   l.add(5);
   l.add(7);
   l.add(9);
   
   // Minimum Integer value as max
   int max = Integer.MIN_VALUE;

   // Using for-each loop
   // to find maximum element
  for(Integer i: l)
   {
       // check if current element is greater than max
       if(i > max)
       {
           // update max
           max = i;
       }
   }
   System.out.println("List of Integers " + l);
   System.out.println("Maximum elemen in a list is: " + max);
    
}

}

`

Output

List of Integers [3, 5, 7, 9] Maximum elemen in a list is: 9

**Explanation: In the above example, we use the for-each loop to iterate the list of integer to find the largest or maximum value in the list. Here, we use the **Integer.MIN_VALUE which is the minimum value of integer and compare it the element of list and check if the element is greater than the max then update the max value.

**Limitations of the For-each Loop

While the for-each loop is convenient, there are some important limitations to consider:

**1. Cannot Modify Array Elements Directly

for (int num : marks) {

// only changes num, not the array element
num = num*2;

}

**Explanation: The for-each loop gives a copy of each element, not a reference. So modifying the loop variable (num in this case) does not affect the actual array or collection. For objects, the loop variable is a reference, so modifying fields of the object will affect the original.

class Person { String name; }

Person[] people = { new Person(“Jeeva”) };

for (Person p : people) {

p.name = “Devanshu”; // Changes original object

p = new Person(); // Does NOT modify array

}

**2. No Access to Index

for (int num : numbers) {

if (num == target) {

// do not know the index of ‘num’ here

return ???; // Index is unavailable in for-each loop

}

}

**Explanation: The for-each loop does not provide access to the index of the current element. If we need the index for any reason (e.g., in a search operation), a traditional loop would be more appropriate.

**3. Single-direction Iteration Only

// Traditional reverse iteration

for (int i = numbers.length – 1; i >= 0; i–) {

System.out.println(numbers[i]); // Reverse iteration not possible with for-each

}

**Explanation: The for-each loop only iterates over the elements in a forward direction. If we need to iterate in reverse, we have to use a traditional for loop with a manually managed index.

**Workaround for Collections:

List list = Arrays.asList(1, 2, 3);

Collections.reverse(list); // Reverse first

for (int num : list) { … } // Now iterates backward

**4. Complex Conditions are Difficult to Implement

for (int i = 0; i < numbers.length; i++) {

if (numbers[i] == arr[i]) {

// Complex conditional checks are easier in a traditional for loop

}

}

**Explanation: If our logic requires checking multiple conditions or using the index in more complex ways, the for-each loop can be limiting. In such cases, a traditional for loop offers more flexibility.

**5. Performance Overhead

// For reliable benchmarks, use JMH instead of manual timing.

List list = new ArrayList<>();

for (int i = 0; i < 1_000_000; i++) list.add(i);

// For-each (iterator-based)

long start = System.nanoTime();

for (int num : list) { … }

long end = System.nanoTime();

System.out.println(“For-each: ” + (end – start) + ” ns”);

// Traditional for (index-based)

start = System.nanoTime();

for (int i = 0; i < list.size(); i++) { … }

end = System.nanoTime();

System.out.println(“Traditional: ” + (end – start) + ” ns”);

**Explanation: The for-each loop uses an iterator for collections (e.g., ArrayList), which adds slight overhead. For arrays, Java optimizes it to a traditional loop.

**Example: This example demonstrates a performance comparison between loop types for iterating over a large list.

Java `

// Java program to compare the performance of // different loop types for // iterating over a large list import java.io.; import java.util.;

class Geeks { public static void main(String[] args) { List list = new ArrayList<>(); long startTime; long endTime;

    // Adding 1 million integers to the list
    for (int i = 0; i < 1000000; i++) 
    {
        list.add(i);
    }

    // Type 1: Using a for-each loop
    startTime = Calendar.getInstance().getTimeInMillis();
    for (int i : list) 
    {
        // Looping over each element
        int a = i;
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println("For each loop :: " + (endTime - startTime) + " ms");

    // Type 2: Using list.size() in the loop condition (with precomputation)
    startTime = Calendar.getInstance().getTimeInMillis();
    int size = list.size();
    for (int j = 0; j < size; j++) 
    {
        // Accessing list elements using index
        int a = list.get(j);
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println("Using collection.size() (precomputed) :: " + 
    (endTime - startTime) + " ms");

    // Type 3: Calculating the collection size before the loop (already optimized)
    startTime = Calendar.getInstance().getTimeInMillis();
    for (int j = 0; j < size; j++) 
    {
        // Accessing list elements using index
        int a = list.get(j);
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println("By calculating collection.size() first :: " + 
    (endTime - startTime) + " ms");

    // Type 4: Iterating the list in reverse order
    startTime = Calendar.getInstance().getTimeInMillis();
    for (int j = size - 1; j >= 0; j--) {
        // Accessing list elements in reverse
        int a = list.get(j);
    }
    endTime = Calendar.getInstance().getTimeInMillis();
    System.out.println("Using [int j = size - 1; j >= 0; j--] (precomputed) :: " +
    (endTime - startTime) + " ms");
}

}

`

Output

For each loop :: 40 ms Using collection.size() (precomputed) :: 23 ms By calculating collection.size() first :: 19 ms Using [int j = size - 1; j >= 0; j--] (precomputed) :: 16 ms

**Explanation: Each time we run the above code, it will give a different output because the execution and the performance times depend on different factors when JVM starts it takes time to optimize so it might appear that the loops work differently. as mentioned the for-each loop uses iterator internally which make a slight performance overhead compared to the traditional for loop.

**Important Points: