Iterator vs Foreach em Java
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
As postagens do blog Acervo Lima te ajudaram? Nos ajude a manter o blog no ar!
Faça uma doação para manter o blog funcionando.
70% das doações são no valor de R$ 5,00...
Diógenes Lima da Silva