
Un iterador permite acceder a cada elemento de una colección sin necesidad de tener que conocer la estructura de esta. Históricamente, Java 1.0 incorpora el iterador Enumeration, posteriormente Java 2 desarrolla dos nuevos iteradores: Iterador y ListIterador.
Enumeration
La interfaz Enumeration declara métodos que recorren una colección. Mediante este tipo de iterador se puede acceder a cada elemento de una colección, pero no permite modificar la colección, es de solo lectura. Enumeration forma parte del paquete java.util. Su declaración es la siguiente:
public interface Enumeration{
boolean hasMoreElements();
Object nextElement();
}
nextElement() devuelve el siguiente elemento. Levanta la excepción de tipo NoSuchElementException si no hay más elementos, es decir si ya se ha recorrido toda la colección. La primera llamada devuelve el primer elemento.
hasMoreElements() devuelve true si no se ha accedido a todos los elementos de la colección. Normalmente se diseña un bucle, controlado por este método, para acceder a cada elemento de la colección.
Las colecciones históricas: Vector, Stack, Dictionary, HashTable disponen del método elements() que devuelve un Enumeration, a partir del cual se puede recorrer la colección. La declaración es la siguiente:
Enumeration elements()
El esquema que se sigue para acceder a cada elemento de una colección consta de los siguientes pasos:
1. Declarar una variable Enumeration.
Enumeration enumera;
2. Llamar al método elements() de la colección.
enumera = coleccion.elements()
3. Diseñar el bucle que obtiene y procesa cada elemento.
while(enumera.hasMoreElements()){
elemento = (TipoElemento)enumera.nextElement();
<proceso de elemento>
}
Ejemplo
Se crea una pila de diferentes objetos, posteriormente, se recorre con un iterador Enumeration y con métodos de Stack. La pila se llena de objetos String, Integer y Double, sin un orden establecido. Para recorrer la pila se crea un enumerador y un bucle hasta que no queden más elementos sin visitar. También se recorre aplicando la operación pop() y controlando que no esté vacía.
import java.util.*;
public class EnumeradorPila {
public static void main(String[] args) {
final int N=8;
Stack pila = new Stack();
String []palabra =
{«Urbion», «Magina», «Abantos», «Peralte», «Citores»};
for(int i=0;i<N;i++){
int n;
n = (int)(Math.random()*N*2);
if(n<palabra.length)
pila.push(palabra[n]);
else if(n<N+2)
pila.push(new Double(Math.pow(n,2)));
else
pila.push(new Integer(n*3));
}
// crea un enumerador de la pila
Enumeration enumera = pila.elements();
// bucle para recorrer la pila
System.out.println(«Elementos de la pila»
+ «en el orden establecido por el enumerador: «);
while(enumera.hasMoreElements()){
Object q;
q = enumera.nextElement();
System.out.print(q + » «);
}
// bucle para recorrer la pila
System.out.println(«\nElementos de la pila en orden LIFO: «);
while(!pila.empty()){
Object q;
q = pila.pop();
System.out.print(q + » «);
}
}
}
Iterator
Java 2 desarrolla nuevas colecciones y el iterador común Iterator. Todo objeto colección se puede recorrer con este iterador. Todas las colecciones tienen el método iterator() que devuelve un objeto Iterator.
Iterator iterador;
iterador = Coleccion.iterator();
La interfaz Iterator permite no solo acceder a los elementos, sino también eliminarlos. Pertenece al paquete java.util; la declaración es la siguiente:
public interface Iterator{
boolean hasNext();
Object next();
void remove();
}
hasNext() devuelve true si quedan elementos no visitados, es el equivalente a hasMoreElements().
next() la primera llamada devuelve el primer elemento, según el orden establecido por el iterador.
remove() elimina de la colección el elemento obtenido por la última llamada a next(). Solo se puede llamar una vez después de next(), en caso contrario, o bien si no ha habido una llamada previa a next(), levanta la excepción IllegalStateException. Normalmente las colecciones implementan este método en un bloque sincronizado.
Norma
Se recomienda utilizar Iterator en lugar de Enumeration usada en colecciones históricas. Los métodos de acceso son más sencillos de recordar y además declara el método remove().
Ejemplo
Dada una lista de puntos del plano se quiere eliminar de la lista aquellos cuya coordenada x esté fuera del rango [2,12]. Se da por declarada la clase Punto con el método int getX(), y que la lista de puntos ya está creada. La lista es del tipo ArrayList. El fragmento de código escrito declara la lista y el iterador; realiza un bucle controlado por hasNext() para acceder a cada elemento y si la coordenada x no está en el rango [2,12] lo elimina llamando al método remove().
class Punto(. . .)
List lista = new ArrayList();
Iterator iterador;
// se llena la lista de objetos Punto
iterador = lista.iterator();
while(iterador.hasNext()){
Punto q;
q = (Punto)iterador.next();
if(q.getX()<2 || q.getX()>12){
System.out.println(«Punto: » +q+ » se elimina»);
iterador.remove();
}
}
La colección guarda elementos de cualquier tipo (Object), esto exige realizar una conversación al tipo concreto (Punto) con el que se trabaja. Con Java 1.5 se puede parametrizar el tipo de los elementos, de tal forma que no es necesario realizar la conversión y, además, el compilador verifica el tipo de los elementos añadidos. A continuación se escribe el código con esta característica.
List<Punto> lista = new ArrayList<Punto>();
Iterator<Punto> iterador;
iterador = lista.iterator();
while(iterador.hasNext()){
Punto q;
q = iterador.next(); // no es necesario un cast
. . .
}