Contexto: 
Iterator é uma interface fornecida pela estrutura de coleção para percorrer uma coleção e para um acesso sequencial de itens na coleção. 
 

   
   // Iterating over collection 'c' using iterator
   for (Iterator i = c.iterator(); i.hasNext(); ) 
       System.out.println(i.next());

Cada loop serve para percorrer os itens de uma coleção. 
 

   // Iterating over collection 'c' using for-each 
   for (Element e: c)
       System.out.println(e);

Lemos o ':' usado em for-each como “in”. Portanto, loop é lido como “para cada elemento e em elementos”, aqui elementos é a coleção que armazena itens do tipo Elemento.

Nota: No Java 8, usando expressões lambda, podemos simplesmente substituir o loop for-each por 
 

elements.forEach (e -> System.out.println(e) );

Diferença entre os dois percursos 
Em for-each loop, não podemos modificar a coleção, ele lançará uma ConcurrentModificationException, por outro lado, com o iterador podemos modificar a coleção. 
 

Modificar uma coleção significa simplesmente remover um elemento ou alterar o conteúdo de um item armazenado na coleção. Isso ocorre porque o loop for-each cria implicitamente um iterador, mas não é exposto ao usuário, portanto, não podemos modificar os itens nas coleções.

Quando usar qual passagem? 
 

  • Se tivermos que modificar a coleção, podemos usar o Iterator. 
     
  • Ao usar loops for aninhados, é melhor usar loop for-each, considere o código a seguir para melhor compreensão.
// Java program to demonstrate working of nested iterators
// may not work as expected and throw exception.
import java.util.*;
 
public class Main
{
    public static void main(String args[])
    {
        // Create a link list which stores integer elements
        List<Integer> l = new LinkedList<Integer>();
 
        // Now add elements to the Link List
        l.add(2);
        l.add(3);
        l.add(4);
 
        // Make another Link List which stores integer elements
        List<Integer> s=new LinkedList<Integer>();
        s.add(7);
        s.add(8);
        s.add(9);
 
        // Iterator to iterate over a Link List
        for (Iterator<Integer> itr1=l.iterator(); itr1.hasNext(); )
        {
            for (Iterator<Integer> itr2=s.iterator(); itr2.hasNext(); )
            {
                if (itr1.next() < itr2.next())
                {
                    System.out.println(itr1.next());
                }
            }
        }
    }
}

Saída: 
 

Exception in thread "main" java.util.NoSuchElementException

    at java.util.LinkedList$ListItr.next(LinkedList.java:888)

    at Main.main(Main.java:29)

O código acima lança java.util.NoSuchElementException. 
 

No código acima, estamos chamando o método next() repetidamente para itr1 (ou seja, para a Lista l). Agora estamos avançando o iterador sem nem mesmo verificar se ele possui mais elementos restantes na coleção (no loop interno), portanto, estamos avançando o iterador mais do que o número de elementos na coleção que leva a NoSuchElementException.

os loops for-each são feitos sob medida para os loops aninhados. Substitua o código do iterador pelo código abaixo.

// Java program to demonstrate working of nested for-each
import java.util.*;
public class Main
{
    public static void main(String args[])
    {
        // Create a link list which stores integer elements
        List<Integer> l=new LinkedList<Integer>();
 
        // Now add elements to the Link List
        l.add(2);
        l.add(3);
        l.add(4);
 
        // Make another Link List which stores integer elements
        List<Integer> s=new LinkedList<Integer>();
        s.add(2);
        s.add(4);
        s.add(5);
        s.add(6);
 
        // Iterator to iterate over a Link List
        for (int a:l)
        {
            for (int b:s)
            {
                if (a<b)
                    System.out.print(a + " ");
            }
        }
    }
}

Saída: 
 

2 2 2 3 3 3 4 4

Análise de desempenho 
 

Percorrer uma coleção usando loops for-each ou iteradores oferece o mesmo desempenho. Aqui, por desempenho, queremos dizer a complexidade do tempo de ambas as travessias.

Se você iterar usando o antigo loop C for estilizado, poderemos aumentar a complexidade do tempo drasticamente.
// Aqui estou uma lista, pode ser ArrayList / LinkedList en é o tamanho da lista 
 

for (i=0;i<n;i++)
   System.out.println(l.get(i));

Aqui, se a lista l é uma ArrayList, podemos acessá-la em tempo O (1), uma vez que são alocados blocos de memória contíguos (como um array), ou seja, o acesso aleatório é possível. Mas se a coleção for LinkedList, então o acesso aleatório não é possível, uma vez que não são alocados blocos de memória contíguos, então, para acessar um elemento, teremos que percorrer a lista de links até chegar ao índice requerido, portanto, o tempo gasto em o pior caso para acessar um elemento será O (n).

O iterador e o loop for-each são mais rápidos do que o loop for simples para coleções sem acesso aleatório, enquanto em coleções que permitem acesso aleatório não há alteração de desempenho com loop for-each / loop for / iterator.

Artigos relacionados: 
Iteradores em Java  
Recuperando elementos da coleção em Java (For-each, Iterator, ListIterator e EnumerationIterator)
Referências:  
https://docs.oracle.com/javase/8/docs/technotes/guides/language/foreach.html  
https://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html  
https://stackoverflow.com/questions/2113216/which-is-more-efficient-a-for-each -loop-or-an-iterator
 

Este artigo é uma contribuição de Chirag Agarwal . Se você gosta de GeeksforGeeks e gostaria de contribuir, você também pode escrever um artigo e enviá-lo para contrib@geeksforgeeks.org. Veja o seu artigo na página principal do GeeksforGeeks e ajude outros Geeks.

Escreva comentários se encontrar algo incorreto ou se quiser compartilhar mais informações sobre o tópico discutido acima