que - ¿Cuáles son los beneficios de la interfaz Iterator en Java?
iterator() java (16)
¿Por qué se usa esta interfaz?
Porque admite las operaciones básicas que permitirían a un programador cliente iterar sobre cualquier tipo de colección (nota: no necesariamente una Collection
en el sentido Object
).
¿Por qué los métodos ... no están codificados directamente en la implementación de la estructura de datos?
Lo son, solo están marcados como Privados, por lo que no puedes alcanzarlos y jugar con ellos. Más específicamente:
- Puede implementar o crear una subclase de un
Iterator
modo que haga algo que los estándares no hacen, sin tener que alterar el objeto real sobre el que itera. - Los objetos que se pueden atravesar no necesitan tener sus interfaces abarrotadas con métodos de cruce, en particular, cualquier método altamente especializado.
- Puedes repartir
Iterators
a cuantos clientes desees, y cada cliente puede atravesar en su propio tiempo, a su propia velocidad. - Los
Iterators
Java del paquete java.util en particular generarán una excepción si el almacenamiento que los respalda se modifica mientras todavía tiene unIterator
fuera. Esta excepción le permite saber que elIterator
ahora puede devolver objetos no válidos.
Para programas simples, nada de esto probablemente parece valer la pena. Sin embargo, el tipo de complejidad que los hace útiles te llegará rápidamente.
Acabo de enterarme de cómo Java Collections Framework implementa estructuras de datos en listas vinculadas. Según lo que entiendo, los Iterators
son una forma de recorrer los elementos en una estructura de datos, como una lista. ¿Por qué se usa esta interfaz? ¿Por qué los métodos hasNext()
, next()
y remove()
no están directamente codificados en la implementación de la estructura de datos?
Desde el sitio web de Java: texto del enlace
interfaz pública Iterador <E>
Un iterador sobre una colección. Iterator toma el lugar de Enumeration en el marco de colecciones de Java. Los iteradores difieren de las enumeraciones de dos maneras:
Esta interfaz es miembro de Java Collections Framework.
- Los iteradores permiten que la persona que llama elimine elementos de la colección subyacente durante la iteración con una semántica bien definida.
- Los nombres de los métodos han sido mejorados.
Intenté buscar en Google y no puedo encontrar una respuesta definitiva. ¿Alguien puede arrojar algo de luz sobre por qué Sun eligió usarlos? ¿Es por un mejor diseño? ¿Seguridad incrementada? Buena práctica OO?
Cualquier ayuda será apreciada. Gracias.
Bueno, parece que el primer punto de la viñeta permite que las aplicaciones de subprocesos múltiples (o de un solo subproceso si se estropea) no necesiten bloquear la colección para detectar infracciones de concurrencia. En .NET, por ejemplo, no puede enumerar y modificar una colección (o lista o cualquier IEnumerable) al mismo tiempo sin bloquear o heredar de los métodos IEnumerable y overriding (obtenemos excepciones).
Creo que es solo una buena práctica de OO. Puede tener un código que trate con todo tipo de iteradores, e incluso le da la oportunidad de crear sus propias estructuras de datos o simplemente clases genéricas que implementen la interfaz del iterador. No tiene que preocuparse por qué tipo de implementación está detrás de esto.
El uso de la interfaz Iterator
permite que cualquier clase que implemente sus métodos actúe como iteradores. La noción de una interfaz en Java es tener, en cierto modo, una obligación contractual de proporcionar ciertas funcionalidades en una clase que implements
la interfaz, para actuar de una manera requerida por la interfaz. Dado que las obligaciones contractuales deben cumplirse para ser una clase válida, otras clases que ven a la clase implements
la interfaz y, por lo tanto, se aseguran de que la clase tendrá esas ciertas funcionalidades.
En este ejemplo, en lugar de implementar los métodos ( hasNext(), next(), remove()
) en la clase LinkedList
, la clase LinkedList
declarará que implements
la interfaz Iterator
, por lo que otros saben que la LinkedList
se puede usar como un iterador. A su vez, la clase LinkedList
implementará los métodos desde la interfaz hasNext()
como hasNext()
), por lo que puede funcionar como un iterador.
En otras palabras, la implementación de una interfaz es una noción de programación orientada a objetos para que los demás sepan que una determinada clase tiene lo que se necesita para ser lo que dice ser.
Esta noción se impone al tener métodos que deben ser implementados por una clase que implementa la interfaz. Esto asegura que otras clases que quieran usar la clase que implementa la interfaz hasNext()
tengan métodos que los Iteradores deberían tener, como hasNext()
.
Además, se debe tener en cuenta que, dado que Java no tiene herencia múltiple, el uso de la interfaz se puede usar para emular esa característica. Al implementar múltiples interfaces, uno puede tener una clase que es una subclase para heredar algunas características, pero también "heredar" las características de otra mediante la implementación de una interfaz. Un ejemplo sería, si quisiera tener una subclase de la clase LinkedList
llamada ReversibleLinkedList
que pudiera iterar en orden inverso, puedo crear una interfaz llamada ReverseIterator
y exigir que proporcione un método previous()
. Como LinkedList
ya implementa Iterator
, la nueva lista reversible habría implementado las interfaces ReverseIterator
y ReverseIterator
.
Puede leer más sobre las interfaces de ¿Qué es una interfaz? de The Java Tutorial from Sun.
En última instancia, porque Iterator captura una abstracción de control que se aplica a una gran cantidad de estructuras de datos. Si está interesado en su teoría de la categoría fu, puede dejarse impresionar por este artículo: La esencia del patrón del iterador .
Iterator es útil cuando se trata de Colecciones en Java.
Use For-Each loop (Java1.5) para iterar sobre una colección, matriz o lista.
Iterator simplemente agrega una forma común de revisar una colección de elementos. Una de las características interesantes es i.remove () en la que puede eliminar elementos de la lista sobre la que está iterando. Si solo intentas eliminar elementos de una lista, normalmente tendría efectos extraños o throw y exception.
La interfaz es como un contrato para todas las cosas que lo implementan. Básicamente estás diciendo ... cualquier cosa que implemente un iterador garantiza que estos métodos se comporten de la misma manera. También puede usarlo para pasar tipos de iteradores si eso es todo lo que le interesa tratar en su código. (es posible que no le importe qué tipo de lista es ... solo desea pasar un iterador) Puede poner todos estos métodos de forma independiente en las colecciones, pero no está garantizando que se comporten igual o que incluso tengan el mismo nombre y firmas.
Los iteradores se pueden usar contra cualquier tipo de colección. Le permiten definir un algoritmo contra una colección de elementos independientemente de la implementación subyacente. Esto significa que puede procesar una lista, conjunto, cadena, archivo, matriz, etc.
En diez años a partir de ahora, podrá cambiar su implementación de List a una mejor implementación y el algoritmo se ejecutará sin problemas en su contra.
Los iteradores son uno de los muchos patrones de diseño disponibles en Java. Los patrones de diseño se pueden considerar como bloques de construcción, estilos y uso de su código / estructura.
Para leer más sobre el patrón de diseño del iterador, consulte este sitio web que habla sobre el iterador y muchos otros patrones de diseño. Aquí hay un fragmento del sitio en Iterator: http://www.patterndepot.com/put/8/Behavioral.html
El iterador es uno de los patrones de diseño más simples y utilizados con mayor frecuencia. El patrón Iterator le permite moverse a través de una lista o colección de datos utilizando una interfaz estándar sin tener que conocer los detalles de las representaciones internas de esos datos. Además, también puede definir iteradores especiales que realicen algún procesamiento especial y devuelvan solo los elementos especificados de la recopilación de datos.
Porque puedes iterar sobre algo que no es una estructura de datos. Digamos que tengo una aplicación en red que extrae los resultados de un servidor. Puedo devolver un contenedor Iterator alrededor de esos resultados y transmitirlos a través de cualquier código estándar que acepte un objeto Iterator.
Piense en ello como una parte clave de un buen diseño de MVC. Los datos tienen que llegar desde el Modelo (es decir, la estructura de datos) a la Vista de alguna manera. El uso de un iterador como intermediario garantiza que la implementación del modelo nunca se exponga. Podría mantener una LinkedList en memoria, sacar información de un algoritmo de desencriptado o ajustar las llamadas JDBC. Simplemente no le importa a la vista, porque a la vista solo le importa la interfaz del iterador.
Se pueden usar varias instancias de un interator simultáneamente. Acérquelos como cursores locales para los datos subyacentes.
Por cierto: favorecer interfaces sobre implementaciones concretas pierde acoplamiento
Busque el patrón de diseño del iterador, y aquí: http://en.wikipedia.org/wiki/Iterator
Solo M2C, si no lo sabía: puede evitar el uso directo de la interfaz del iterador en situaciones donde el bucle for-each será suficiente.
Un documento interesante sobre los pro y los contras del uso de iteradores:
Usted pregunta: "¿Por qué los métodos hasNext (), next () y remove () no están directamente codificados en la implementación de la estructura de datos?".
El marco de Java Collections elige definir la interfaz Iterator como externalizada a la colección misma. Normalmente, dado que cada colección Java implementa la interfaz Iterable
, un programa Java llamará a iterator
para crear su propio iterador para que pueda ser utilizado en un bucle. Como han señalado otros, Java 5 nos permite dirigir el uso del iterador, con un bucle for-each.
La externalización del iterador a su colección permite al cliente controlar cómo se itera a través de una colección. Un caso de uso en el que puedo pensar que es útil es cuando uno tiene una colección ilimitada, como todas las páginas web en Internet para indexar.
En el clásico libro de GoF, el contraste entre los iteradores internos y externos se explica con bastante claridad.
Un problema fundamental es decidir qué parte controla la iteración, el iterador o el cliente que usa el iterador. Cuando el cliente controla la iteración, el iterador se denomina iterador externo, y cuando el iterador lo controla, el iterador es un iterador interno. Los clientes que usan un iterador externo deben avanzar el recorrido y solicitar explícitamente el siguiente elemento del iterador. En contraste, el cliente le entrega a un iterador interno una operación para realizar, y el iterador aplica esa operación a cada elemento ....
Los iteradores externos son más flexibles que los iteradores internos. Es fácil comparar dos colecciones para igualdad con un iterador externo, por ejemplo, pero es prácticamente imposible con iteradores internos ... Pero, por otro lado, los iteradores internos son más fáciles de usar, porque definen la lógica de iteración para usted.
Para ver un ejemplo de cómo funcionan los iteradores internos, consulte la API Enumerable
de Ruby, que tiene métodos de iteración interna, como each
. En Ruby, la idea es pasar un bloque de código (es decir, un cierre) a un iterador interno para que una colección pueda ocuparse de su propia iteración.
es importante mantener la colección aparte del puntero. el iterador apunta a un lugar específico en una colección, y por lo tanto no es una parte integral de la colección. De esta forma, para una instancia, puede usar varios iteradores sobre la misma colección.
El lado negativo de esta separación es que el iterador no tiene conocimiento de los cambios realizados en la colección que itera. por lo que no puede cambiar la estructura de la colección y esperar que el iterador continúe su trabajo sin "quejas".
La interfaz java.util.Iterator se utiliza en Java Collections Framework para permitir la modificación de la colección sin dejar de iterar a través de ella. Si solo quieres iterar limpiamente sobre una colección completa, utiliza una para cada uno, pero una ventaja de iteradores es la funcionalidad que obtienes: una operación opcional de eliminación () e incluso mejor para la interfaz List Iterator, que ofrece agregar () y set () también. Ambas interfaces le permiten iterar sobre una colección y cambiarla estructuralmente al mismo tiempo. Intentar modificar una colección mientras se itera a través de ella arrojará una ConcurrentModificationException, ¡generalmente porque la colección se ha modificado inesperadamente!
Eche un vistazo a la clase ArrayList
Tiene 2 clases privadas dentro (clases internas) llamadas Itr y ListItr
Implementan las interfaces Iterator y ListIterator respectivamente
clase pública ArrayList ..... {// clase adjunta
private class Itr implements Iterator<E> {
public E next() {
return ArrayList.this.get(index++); //rough, not exact
}
//we have to use ArrayList.this.get() so the compiler will
//know that we are referring to the methods in the
//enclosing ArrayList class
public void remove() {
ArrayList.this.remove(prevIndex);
}
//checks for...co mod of the list
final void checkForComodification() { //ListItr gets this method as well
if (ArrayList.this.modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
}
private class ListItr extends Itr implements ListIterator<E> {
//methods inherted....
public void add(E e) {
ArrayList.this.add(cursor, e);
}
public void set(E e) {
ArrayList.this.set(cursor, e);
}
}
}
Cuando llama a los métodos iterator () y listIterator (), devuelven una nueva instancia de la clase privada Itr o ListItr, y dado que estas clases internas están "dentro" de la clase ArrayList adjunta, pueden modificar libremente ArrayList sin activar una ConcurrentModificationException , a menos que cambie la lista al mismo tiempo (concisamente) a través de los métodos set () add () o remove () de la clase ArrayList.