There is a collection and a loop foreach
:
List & lt; String & gt; someList = new ArrayList & lt; String & gt; ();
// add "monkey", "donkey", "skeleton key" to someList
for (String item: someList)
System.out.println (item);
What does the for
loop look like, which is equivalent to the foreach
loop above? How does the foreach
loop work internally? What is the difference between for
and foreach
loops?
Answer 1, authority 100%
The
foreach
loop is syntactic sugar. Outwardly, it primarily differs from for
in 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 [] // arrays of any type
- Objects that implement the
Iterable
.
for
loop that works with Iterable
objects
Code from question
for (String item: someList)
System.out.println (item);
is equal to the code below
for (Iterator & lt; E & gt; 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 foreach
loop cannot be used method remove (index)
. Use iterator.remove ()
instead. Example:
for (Iterator & lt; Integer & gt; iterator = list.iterator (); iterator.hasNext ();)
if (iterator.next () & gt; 10)
iterator.remove ();
If you write for
without using an iterator, then here is an example implementation of foreach
:
for (int i = 0; i & lt; list.size (); i ++)
System.out.println (list.get (i));
foreach
and for
loops that work with arrays
String [] fruits = new String [] {"Orange", "Apple", "Pear", "Strawberry "};
for (String fruit: fruits) {
// fruit is an element of the `fruits` array.
}
is essentially equivalent to
for (int i = 0; i & lt; 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 for
. However, when accessing arrays – at least with arrays of primitives and wrappers – access via indices (i.e. using for
) is faster.
Also nested foreach
performance problems occur from -for creating a large number of Iterator
objects.
Java 8 introduced streams that perform better overall.
(although this information is not directly related to the question, but it can be useful)
To work 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: Measuring Performance on JDK9
(do not seriously evaluate it, because it does not seem to me that I measured everything correctly)
To measure performance, I used code from this question:
public static void main (String [] args) {
System.out.println (getTime ());
}
private static void testMethod () {
// Code, the execution time of which you need to find out
}
/ **
* Method for measuring the execution time of the testMethod method
* https://stackoverflow.com/a/2404378/7150209
* /
private static double getTime () {
for (int i = 0; i & lt; 20; i ++) {// warming up the JVM
testMethod ();
}
int count = 1000; // initial number of times to retry testMethod
while (true) {
long begin = System.nanoTime ();
for (int i = 0; i & lt; count; i ++)
testMethod ();
long end = System.nanoTime ();
if ((end - begin) & lt; 1000000000) {// Run tests while total execution count times
count * = 100000; // testMethod`a will not be equal for several seconds
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
times. Before the start of the launches, the time is recorded, after all the launches, the initial time is subtracted from the end 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 run of the test method is obtained. If the time to run count times the test method & lt; 10 seconds, then count is increased, and the measurement is repeated.
In the test method in the for
and foreach
loops, I used:
variable = list.get (i)
/ array [i]
for for
and variable = i;
for foreach
.
In the lambda, I used Arrays.stream (array) .map (l - & gt; l + 1) .collect (Collectors.toList ());
and list.stream () .map (l - & gt; l + 1) .collect (Collectors.toList ())
i.e. changing the elements of the collection and creating a new collection, so the lambdas took longer to execute.
The table shows that the execution in the lambda took about the same time for collections and arrays. The execution time of code 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.
P.S. Example code for
and foreach
for a collection (n is just a variable):
for (int i = 0; i & lt; list.size (); i ++)
n = list.get (i);
and
for (int i: list)
n = i;