How does the foreach loop work in Java?


There is a collection and a loop foreach:

List<String> someList = new ArrayList<String>();
//add "monkey", "donkey", "skeleton key" to someList

for(String item : someList) 
  System.out.println(item);

What does the for loop equivalent to the foreach loop above look like? How does the foreach loop work inside? What is the difference between the for and foreach cycles?

Author: DaemonHK, 2019-02-12

1 answers

The foreach loop is syntactic sugar. Externally, first of all, it differs from for by the absence of an explicit counter. The only practical difference between the two is that in the case of indexed objects, you don't have access to the index.

The foreach loop allows you to iterate over two types of objects:

  • T[] //массивы любого типа
  • Objects that implement the interface Iterable.

Loop for that works with objects Iterable

Code from the question

for(String item : someList) 
      System.out.println(item);

Is equal to the code below

for (Iterator<E> i = someIterable.iterator(); i.hasNext();) {
    String item = i.next();
    System.out.println(item);
}

This code works for any object that implements the interface Iterable.


In the loop foreach you cannot use the method remove(index). Instead, use iterator.remove(). Example:

for (Iterator<Integer> iterator = list.iterator(); iterator.hasNext(); )
    if (iterator.next() > 10)
        iterator.remove();

If you write for without using an iterator, then here is an example implementation of foreach:

for(int i = 0; i < list.size(); i++)
  System.out.println(list.get(i));

Loops foreach and for that work with arrays

String[] fruits = new String[] { "Orange", "Apple", "Pear", "Strawberry" };

for (String fruit : fruits) {
    // fruit is an element of the `fruits` array.
}

Essentially equivalent to

for (int i = 0; i < fruits.length; i++) {
    String fruit = fruits[i];
    // fruit is an element of the `fruits` array.
}

foreach vs for - performance

When accessing a collection, foreach significantly faster than than for. However, when accessing arrays - at least with arrays of primitives and wrappers - access via indexes(i.e. using for) is faster.

Also with nested loops foreach performance problems are observed due to the creation of a large number of objects Iterator.


Java 8 introduced threads that generally perform better. (although this information is not directly relevant to the question, it may be useful)

For working with collections:

someList.stream().forEach(System.out::println);

To work with an array:

Arrays.stream(someArray).forEach(System.out::println);

Oracle documentation for foreach.


UPD: Performance measurement on JDK9

(do not seriously evaluate it, because I do not think that I have measured everything correctly)

For I used the code from of this question to measure performance:

 public static void main(String[] args) {
    System.out.println(getTime());
}

private static void testMethod() {
    //Код, время выполнения которого нужно узнать
}

/**
 * Метод для измерения времени выполнения метода testMethod
 * https://stackoverflow.com/a/2404378/7150209
 */
private static double getTime() {
    for (int i = 0; i < 20; i ++) { //прогрев JVM
        testMethod();
    }
    int count = 1000; //первоначальное кол-во повтора выполнения testMethod

    while(true) {
        long begin =  System.nanoTime();

        for (int i = 0; i < count; i ++)
            testMethod();

        long end = System.nanoTime();

        if ((end - begin) < 1000000000) { //Прогон тестов пока суммарное выполнения count раз
            count *= 100000;              //testMethod`a не будет равно несколько секунд
            continue;
        }

        return (double)(end - begin) / count;
    }
}

How the getTime() method works - in the for loop, the method with the code under test is run count once. Before the start of the launches, the time is checked, after all the launches, the initial time is subtracted from the final time - the time of launching count times of the test method is obtained. After that, the time is divided by count-the average time of one test method run is obtained. If the run time of count times of the test method is

In the test method in the cycles for and foreach I used: переменная = list.get(i)/array[i] for for and переменная = i; для foreach.

In lambda, I used Arrays.stream(array).map(l -> l+1).collect(Collectors.toList()); and list.stream().map(l -> l+1).collect(Collectors.toList()), i.e. changing collection items and creating a new collection, so lambdas took longer to execute.

enter a description of the image here

The table shows that the execution in lambda took about the same time for collections and arrays. Time code execution with an array is about 1.5 times faster than with a collection. The execution time of the for and foreach loops is the same for all of them.

P.S. Example code for and foreach for a collection(n is just a variable):

for(int i = 0; i < list.size(); i++)
   n = list.get(i);

And

for(int i : list)
  n = i; 
 14
Author: Anton Sorokin, 2019-02-17 16:44:23