assintoticamente, a performance sera a mesma. mas a segunda maneira vai ter uma performance MUITO pior se fosse uma LinkedList, por isso é recomendado sempre usarmos o Iterator quando percorremos uma List, ja que nao sabemos sua real implementacao.
Voce pode usar o enhanced for para melhor legibilidade, que vai acabar usando o iterator:
for(ContatoT c : contatos) {
System.out.println(c.getNome());
}
O método 2 é mais legível? :shock:
Isso é legível:
for(ContatoT contato : listaContatos){
System.out.println (contato.getNome());
}
E sobre a performance, utilizar Iterator é ligeiramente mais lento ( a diferença em geral é mais por preciosismo do que realismo ), mas gera menos perigo e trabalho do que trabalhar com array puro.
Até!
Obs.: não vi que o Paulo tinha respondido, mas já tinha apertado o botao e não tinha resposta.
Aquele cast ali é desnecessário no método 1. Basta criar o iterator como um Iterator<ContatoT>, já que sua lista é de ContatoT:
for (Iterator<ContatoT> iterator = contatos.iterator(); iterator.hasNext(); ) {
ContatoT c = iterator.next();
System.out.println (c.getNome());
}
Outro comentário. Se você for excluir elementos enquanto percorre o ArrayList, será obrigado a usar o iterator e excluir através dele, ou então receberá um ConcurrentModificationException.
Exemplo que funciona:
public void apagaPorNome(String nome) {
Iterator<ContatoT> it = contatos.iterator();
while (it.hasNext()) {
ContatoT contato = it.next();
if (contato.getNome().startsWith(nome))
it.remove(); //Única forma de remover enquanto percorre
}
}
Exemplo que dá erro:
public void apagaPorNome(String nome) {
for (ContatoT contato : contatos) {
if (contato.getNome().startsWith(nome))
contatos.remove(contato); //Vai fazer o for gerar um ConcurrentModificationException
}
}
Outra dica. Ao postar códigos, use a tag code. É o que está fazendo essa formatação bonitinha nos nossos códigos. Isso nos ajuda a entender melhor o seu problema. Se não sabe ou tem dúvidas de como fazer isso, por favor, leia o tópico: http://www.guj.com.br/posts/list/50115.java
for (Iterator iterator = contatos.iterator(); iterator.hasNext(); ) {
ContatoT c = iterator.next();
System.out.println (c.getNome());
}
Método 03
for(ContatoT c : contatos) {
System.out.println(c.getNome());
}
Método 04
Iterator<ContatoT> it = contatos.iterator();
while (it.hasNext()) {
ContatoT c = it.next();
System.out.println(c.getNome());
}
Vamos ao que eu acho que entendi:
Método 01 - Só poderia ser considerado se fosse um arraylist, demais tipos de coleções deve-se usar iteratos
Método 02 - “for” usando iterator
Método 03 - Seria o “for each”/“enchanced for”, introduzido no java 1.5, onde o iterator fica implicito
Método 04 - Usando while(Este método achei o mais “feio” de todos)
Estas minhas considerações estao certas?
Outras dúvidas:
-existe diferença de performance entre os métodos 02 e 03?
-viniGodoy, poderia explicar o porquê do erro “ConcurrentModificationException” no exemplo que vc deu?
public void apagaPorNome(String nome) {
for (ContatoT contato : contatos) {
if (contato.getNome().startsWith(nome))
contatos.remove(contato); //Vai fazer o for gerar um ConcurrentModificationException
}
}
A diferença de performance vai ser alguns microsegundos por iteração. A não ser que a sua lista tenha mais do que 1 milhão de objetos eu não me preocuparia com performance e usaria o modo mais claro.
Usando um iterator vc leaka iterator. Até o NIO Selector do Java faz isso (e leaka Integers tb). Isso sobrecarrega o GC. Talvez introduza 2 ms de latência no seu programa. Provavelmente vc pode viver sem esses 2 ms.
Se fosse LinkedList, aí eu te recomendaria usar o Iteartor sem dúvida, devido a diferença entre ArrayList e LinkedList.
Considere o risco de um iterator que não faz isso. Você itera até a penultima posição. Então, paralelamente, alguém (que pode ser seu próprio método de exclusão) vai lá e exclui 2 registros. Logo depois, você tenta avançar uma posição. Lembre-se: seu iterator não sabe que os registros foram excluídos, nem quais foram. O que acontece? Você provavalmente cairia num IndexOutOfBounds. Fora isso, o iterator poderia, sem saber, ter uma posição “pulada” e acabar não fazendo o comportamento esperado. Por exemplo, você está excluindo todos os 3 “João” da sua lista ordenada. Após excluir o primeiro, algum outro trecho do programa exclui uma “Ana”. O iterator do João, acaba ficando posicionado no último João (já que a Ana vem antes do João, o que fez todos os elementos posteriores voltarem uma posição), pulando o João do meio, e seu método simplesmente não realiza aquela exclusão. Inconsistente, não?
Por isso, o iterator faz uma verificação e não navegará mais se exclusões forem feitas paralelamente.
A maneira “segura” de se excluir enquanto se percorre uma lista é através do Iterator. Assim, ele fica sabendo não só que houve uma exclusão, mas também quem foi excluído e se é ou não possível continuar iterando.
Em alguns métodos, onde você só precisa de informação filtrada, as vezes é mais fácil fazer uma cópia da lista. Aí você itera pela lista original, e exclui objetos da cópia. A performance disso não é maravilhosa, mas é extremamente simples de se implementar, gera um código limpo e bastante válido para listas pequenas.
PS: Existem listas que tem Iterators mais espertos no pacote java.util.concurrent. Se você realmente precisar de uma lista com acessos em paralelo, use as listas desse pacote.