Um guia para o iterador em Java
1. Introdução
UmIterator é uma das muitas maneiras pelas quais podemos percorrer uma coleção e, como toda opção, tem seus prós e contras.
Foi introduzido pela primeira vez em Java 1.2 como uma substituição deEnumerationse:
-
introduziu nomes de métodos aprimorados
-
tornou possível remover elementos de uma coleção sobre a qual estamos iterando
-
não garante ordem de iteração
Neste tutorial, vamos revisar a interface simplesIterator para aprender como podemos usar seus diferentes métodos.
Também verificaremos a extensãoListIterator mais robusta, que adiciona algumas funcionalidades interessantes.
2. A interfaceIterator
Para começar, precisamos obter umIterator de aCollection; isso é feito chamando o métodoiterator().
Para simplificar, obteremos a instânciaIterator de uma lista:
List items = ...
Iterator iter = items.iterator();
A interfaceIterator tem três métodos principais:
2.1. hasNext()
O métodohasNext() pode ser usado para verificar se há pelo menos um elemento restante para iterar.
É projetado para ser usado como uma condição em loops dewhile:
while (iter.hasNext()) {
// ...
}
2.2. next()
O métodonext() pode ser usado para passar pelo próximo elemento e obtê-lo:
String next = iter.next();
É uma boa prática usarhasNext() antes de tentar chamarnext().
Iterators paraCollections não garante iteração em nenhuma ordem específicaunless particular implementation provides it.
2.3. remove()
Finalmente, se quisermosremove the current element from the collection,, podemos usar oremove:
iter.remove();
Esta é uma maneira segura de remover elementos durante a iteração em uma coleção sem o risco deConcurrentModificationException.
2.4. Exemplo deIterator completo
Agora podemos combinar todos eles e ver como usamos os três métodos juntos para filtrar coleções:
while (iter.hasNext()) {
String next = iter.next();
System.out.println(next);
if( "TWO".equals(next)) {
iter.remove();
}
}
É assim que normalmente usamos umIterator,, verificamos com antecedência se há outro elemento, o recuperamos e, em seguida, executamos alguma ação nele.
2.5. Iterando com expressões lambda
Como vimos nos exemplos anteriores, é muito prolixo usar umIterator quando queremos apenas revisar todos os elementos e fazer algo com eles.
Desde Java 8, temos o métodoforEachRemaining que permite o uso de lambdas para processar os elementos restantes:
iter.forEachRemaining(System.out::println);
3. A interfaceListIterator
ListIterator é uma extensão que adiciona uma nova funcionalidade para iteração nas listas:
ListIterator listIterator = items.listIterator(items.size());
Observe como podemos fornecer uma posição inicial que, neste caso, é o final doList.
3.1. hasPrevious() eprevious()
ListIterator pode ser usado para retrocesso, portanto, fornece equivalentes dehasNext()enext():
while(listIterator.hasPrevious()) {
String previous = listIterator.previous();
}
3.2. nextIndex() epreviousIndex()
Além disso, podemos percorrer índices e não elementos reais:
String nextWithIndex = items.get(listIterator.nextIndex());
String previousWithIndex = items.get(listIterator.previousIndex());
Isso pode ser muito útil no caso de precisarmos saber os índices dos objetos que estamos modificando atualmente, ou se quisermos manter um registro dos elementos removidos.
3.3. add()
O métodoadd, que, como o nome sugere, nos permite adicionar um elementobefore the item that would be returned by next() and after the one returned by previous():
listIterator.add("FOUR");
3.4. set()
O último método que vale a pena mencionar éset(),, que nos permite substituir o elemento que foi retornado na chamada paranext() ouprevious():
String next = listIterator.next();
if( "ONE".equals(next)) {
listIterator.set("SWAPPED");
}
É importante observar quethis can only be executed if no prior calls to add() or remove() were made.
3.5. Exemplo deListIterator completo
Agora podemos combinar todos eles para dar um exemplo completo:
ListIterator listIterator = items.listIterator();
while(listIterator.hasNext()) {
String nextWithIndex = items.get(listIterator.nextIndex());
String next = listIterator.next();
if("REPLACE ME".equals(next)) {
listIterator.set("REPLACED");
}
}
listIterator.add("NEW");
while(listIterator.hasPrevious()) {
String previousWithIndex
= items.get(listIterator.previousIndex());
String previous = listIterator.previous();
System.out.println(previous);
}
Neste exemplo, começamos obtendoListIterator deList, então podemos obter o próximo elemento por índice -which doesn’t increase the iterator’s internal current element - ou chamandonext.
Então, podemos substituir um item específico porsete inserir um novo comadd.
Depois de chegar ao final da iteração, podemos voltar para modificar elementos adicionais ou simplesmente imprimi-los de baixo para cima.
4. Conclusão
A interfaceIterator nos permite modificar uma coleção enquanto a percorremos, o que é mais difícil com uma instrução for / while simples. Isso, por sua vez, fornece um bom padrão que podemos usar em muitos métodos que requerem apenas o processamento de coleções, mantendo boa coesão e baixo acoplamento.
Finalmente, como sempre, o código-fonte completo está disponívelover at GitHub.