Estruturas de dados: Iteradores

Computação II - Ciência da Computação


Prof.: Danilo S. Carvalho

Nessa aula, aprenderemos sobre como percorrer uma coleção de maneira genérica.


Ao final da aula, saberemos como obter iteradores a partir de coleções e como usá-los para acessar os elementos de uma coleção, independente de como estão organizados.

Em certos momentos, vamos precisar acessar os elementos (objetos) de uma coleção em ordem arbitrária, que pode ser característica da coleção.


Para isso, cada tipo de coleção possui um método iterator(), que retorna um iterador: isto é, um objeto que contém uma referência para o "primeiro" elemento da coleção, que pode ser solicitado a avançar a referência para os elementos seguintes, um a um.

Vejamos o exemplo do HashSet<E>:

Após criarmos o conjunto e adicionar os elementos, obtemos o iterador.

Com o iterador, podemos acessar um a um cada um dos elementos do conjunto, mesmo esse não possuindo uma ordem definida.

                        
                            import java.util.*;

                            public class ExemploIterador {

                            public static void main(String args[]) {
                                HashSet<String> conjunto = new HashSet<String>();
                                
                                conjunto.add("Um");
                                conjunto.add("Dois");
                                conjunto.add("Três");
                                conjunto.add("Quatro");
                                
                                Iterator iter = conjunto.iterator();
                                
                                while(iter.hasNext()) {
                                    Object elemento = (String)iter.next();
                                    System.out.print((elemento + " ");
                                }
                            }
                        }    
                        
                    

Um iterador básico possui os seguintes métodos:

boolean hasNext(): indica se há mais um elemento na coleção.

Object next(): obtem a referência ao objeto na próxima posição do iterador.

Object remove(): remove a referência ao último objeto retornado pelo iterador da coleção que gerou o iterador. Deve-se chamar next() em seguida.

                        
                            import java.util.*;

                            public class ExemploIterador {

                            public static void main(String args[]) {
                                HashSet<String> conjunto = new HashSet<String>();
                                
                                conjunto.add("Um");
                                conjunto.add("Dois");
                                conjunto.add("Três");
                                conjunto.add("Quatro");
                                
                                Iterator iter = conjunto.iterator();
                                
                                if (iter.hasNext()) {
                                    String elemento = (String)iter.next();  // elemento.equals("Um")
                                }
                                if (iter.hasNext()) {
                                    String elemento = (String)iter.next(); // elemento.equals("Dois")
                                    iter.remove();

                                    // Imprime uma permutação de ["Um", "Três", "Quatro"]
                                    System.out.println(conjunto.toString()); 
                                }
                            }
                        }    
                        
                    

Dependendo da coleção, os iteradores podem ter mais métodos, refletindo características específicas da coleção.


Por exemplo exemplo o iterador da classe ArrayList<E>, possui o método previous() que retorna o elemento anterior ao atual do iterador, devido a lista ter ordem definida.


Já a classe HashMap<K, V>, não possui método para gerar um iterador, mas fornece acesso às coleções respectivas as suas chaves e valores, das quais os iteradores podem ser obtidos.

Entendemos agora como percorrer os elementos de uma coleção qualquer, gerando um iterador para ela e usando os métodos de iteração.


Já estamos capacitados a navegar pelos elementos de coleções diversas.


A partir daqui, vamos nos ocupar com a passagem dos dados genéricos para dentro e para fora dos nossos programas.

Perguntas:

  1. O que fazemos quando um iterador chega no fim e queremos iterar novamente?
  2. O que acontece caso a coleção para qual um iterador foi gerada for modificada?

Até a próxima aula!