59

Consider the following scenario.

List<String> list = new ArrayList<>();

Now I added the String values for this list.

I used following ways to go each and every element in the list.

Option one- use for-each

for (String i : list) {
        System.out.println(i);
    } 

Option two- use Iterator

Iterator it=list.iterator();
while (it.hasNext()){
   System.out.println(it.next());
}

I just want to know is there any performance advantage if I use for-each instead of Iterator. And also is it a bad practice to use Iterator now a days in Java?

Ruchira Gayan Ranaweera
  • 34,993
  • 17
  • 75
  • 115

8 Answers8

106

for-each is syntactic sugar for using iterators (approach 2).

You might need to use iterators if you need to modify collection in your loop. First approach will throw exception.

for (String i : list) {
    System.out.println(i);
    list.remove(i); // throws exception
} 

Iterator it=list.iterator();
while (it.hasNext()){
    System.out.println(it.next());
    it.remove(); // valid here
}
Tala
  • 8,888
  • 5
  • 34
  • 38
  • 10
    Of course its good to remember that adding/removing items from the collection that you're looping over is not good practice, for the very reason that you highlighted. – Jeremy Jan 29 '16 at 10:35
19

The difference is largely syntactic sugar except that an Iterator can remove items from the Collection it is iterating. Technically, enhanced for loops allow you to loop over anything that's Iterable, which at a minimum includes both Collections and arrays.

Don't worry about performance differences. Such micro-optimization is an irrelevant distraction. If you need to remove items as you go, use an Iterator. Otherwise for loops tend to be used more just because they're more readable ie:

for (String s : stringList) { ... }

vs:

for (Iterator<String> iter = stringList.iterator(); iter.hasNext(); ) {
  String s = iter.next();
  ...
}
Ravi
  • 30,829
  • 42
  • 119
  • 173
Ashish Chaurasia
  • 1,747
  • 17
  • 23
13

for-each is an advanced looping construct. Internally it creates an Iterator and iterates over the Collection. Only possible advantage of using an actual Iterator object over the for-each construct is that you can modify your collection using Iterator's methods like .remove(). Modifying the collection without using Iterator's methods while iterating will produce a ConcurrentModificationException.

Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
Aniket Thakur
  • 66,731
  • 38
  • 279
  • 289
3

Simple answers: No and no.

Internally the for-each loop creates an Iterator to iterate through the collection.

The advantage of using the Iterator explicitly is that you can access the Iterators method.

Uwe Plonus
  • 9,803
  • 4
  • 41
  • 48
3

Best way to do this is in java 8 is,

list.forEach(System.out::println);

Here are some useful links.

  1. Java 8 Iterable.forEach() vs foreach loop

  2. http://www.javaworld.com/article/2461744/java-language/java-language-iterating-over-collections-in-java-8.html

  3. https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html

Community
  • 1
  • 1
Maleen Abewardana
  • 13,600
  • 4
  • 36
  • 39
  • 1
    why do you think it's better using list.foreach()? in as such feaeach() method you cannot modify a extern var and have to copy it as final or wrap it in an array. – Sheldon Wei Jan 31 '18 at 01:50
2

Here is simple code snippet to check the performance of For-each vs Iterator vs for for the traversal of ArrayList<String>, performed on Java version 8.

        long MAX = 2000000;

        ArrayList<String> list = new ArrayList<>();

        for (long i = 0; i < MAX; i++) {

            list.add("" + i);
        }

        /**
         * Checking with for each iteration.
         */
        long A = System.currentTimeMillis();

        for (String data : list) {
            // System.out.println(data);
        }

        long B = System.currentTimeMillis();
        System.out.println(B - A + "ms");

        /**
         * Checking with Iterator method
         */

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            iterator.next();
            // System.out.println(iterator.next());
        }

        long C = System.currentTimeMillis();
        System.out.println(C - B + "ms");

        /**
         * Checking with normal iteration.
         */
        for (int i = 0; i < MAX; i++) {
            list.get((int) (i % (MAX - i)));
            // System.out.println(list.get(i));
        }

        long D = System.currentTimeMillis();
        System.out.println(D - C + "ms");

Average Output values:

19ms
9ms
27ms

Result Analysis: Iterator (9ms) < For-each (19ms) < For (27ms)

Here Iterator has the best performance and For has the least performance. However For-each performance lies somewhere in between.

Community
  • 1
  • 1
Rahul Raina
  • 3,322
  • 25
  • 30
0

If you want to replace items in your List, I would go old school with a for loop

for (int nIndex=0; nIndex < list.size(); nIndex++) {
  Obj obj = (Obj) list.get(nIndex);

  // update list item
  list.set(nIndex, obj2);
}
Bob
  • 11
  • 1
0

foreach uses iterators under the hood anyway. It really is just syntactic sugar.

Consider the following program:

import java.util.List;
import java.util.ArrayList;

public class Whatever {
    private final List<Integer> list = new ArrayList<>();
    public void main() {
        for(Integer i : list) {
        }
    }
}

Let's compile it with javac Whatever.java,
And read the disassembled bytecode of main(), using javap -c Whatever:

public void main();
  Code:
     0: aload_0
     1: getfield      #4                  // Field list:Ljava/util/List;
     4: invokeinterface #5,  1            // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
     9: astore_1
    10: aload_1
    11: invokeinterface #6,  1            // InterfaceMethod java/util/Iterator.hasNext:()Z
    16: ifeq          32
    19: aload_1
    20: invokeinterface #7,  1            // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
    25: checkcast     #8                  // class java/lang/Integer
    28: astore_2
    29: goto          10
    32: return

We can see that foreach compiles down to a program which:

  • Creates iterator using List.iterator()
  • If Iterator.hasNext(): invokes Iterator.next() and continues loop

As for "why doesn't this useless loop get optimized out of the compiled code? we can see that it doesn't do anything with the list item": well, it's possible for you to code your iterable such that .iterator() has side-effects, or so that .hasNext() has side-effects or meaningful consequences.

You could easily imagine that an iterable representing a scrollable query from a database might do something dramatic on .hasNext() (like contacting the database, or closing a cursor because you've reached the end of the result set).

So, even though we can prove that nothing happens in the loop body… it is more expensive (intractable?) to prove that nothing meaningful/consequential happens when we iterate. The compiler has to leave this empty loop body in the program.

The best we could hope for would be a compiler warning. It's interesting that javac -Xlint:all Whatever.java does not warn us about this empty loop body. IntelliJ IDEA does though. Admittedly I have configured IntelliJ to use Eclipse Compiler, but that may not be the reason why.

enter image description here

Birchlabs
  • 7,437
  • 5
  • 35
  • 54