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?
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.
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;