Pregunta

Acabo de enterarme de cómo Java Collections Framework implementa estructuras de datos en listas vinculadas.Por lo que tengo entendido, Iterators son una forma de recorrer los elementos de una estructura de datos como una lista.¿Por qué se utiliza esta interfaz?¿Por qué los métodos hasNext(), next() y remove() ¿No está codificado directamente en la implementación de la estructura de datos?

Desde el sitio web de Java: Texto del enlace

Iterador de interfaz pública<E>

Un iterador sobre una colección.Iterator toma el lugar de enumeración en el marco de colecciones Java.Los iteradores difieren de las enumeraciones de dos maneras:

  • Los iteradores permiten que la persona que llama elimine elementos de la colección subyacente durante la iteración con semántica bien definida.
  • Se han mejorado los nombres de métodos.
Esta interfaz es miembro del marco de colecciones Java.

Intenté buscar en Google y parece que no puedo encontrar una respuesta definitiva.¿Alguien puede arrojar algo de luz sobre por qué Sun decidió utilizarlos?¿Es por un mejor diseño?¿Seguridad incrementada?¿Buena práctica de OO?

Cualquier ayuda será apreciada.Gracias.

¿Fue útil?

Solución

¿Por qué se utiliza 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 un Collection en el Object sentido).

¿Por qué los métodos...?¿No está codificado directamente a la implementación de la estructura de datos?

Lo son, simplemente están marcados como Privados para que no puedas acceder a ellos y jugar con ellos.Más específicamente:

  • Puede implementar o subclasificar un Iterator de modo que haga algo que los estándar 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 de métodos transversales, en particular métodos altamente especializados.
  • puedes repartir Iterators a todos los clientes que desee, y cada cliente puede recorrerlo en su propio tiempo, a su propia velocidad.
  • Java Iterators del paquete java.util en particular generará una excepción si el almacenamiento que los respalda se modifica mientras aún tiene una Iterator afuera.Esta excepción le permite saber que el Iterator Es posible que ahora esté devolviendo objetos no válidos.

Para programas simples, probablemente nada de esto parezca valer la pena.Sin embargo, el tipo de complejidad que los hace útiles se dará cuenta rápidamente.

Otros consejos

Usted pregunta:"¿Por qué los métodos hasNext(), next() y remove() no están codificados directamente en la implementación de la estructura de datos?".

El marco de colecciones de Java elige definir la interfaz Iterator como externalizada a la propia colección.Normalmente, dado que cada colección Java implementa el Iterable interfaz, un programa Java llamará iterator para crear su propio iterador para que pueda usarse en un bucle.Como otros han señalado, 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 en el que esto es útil es cuando uno tiene una colección ilimitada, como todas las páginas web de Internet, para indexar.

En el libro clásico de GoF, el contraste entre iteradores internos y externos se explica con bastante claridad.

Una cuestión fundamental es decidir qué parte controla la iteración, el iterador o el cliente que utiliza 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 utilizan un iterador externo deben avanzar en el recorrido y solicitar el siguiente elemento explícitamente al iterador.Por el contrario, 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 la igualdad de dos colecciones 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 por usted.

Para ver un ejemplo de cómo funcionan los iteradores internos, consulte Ruby's Enumerable API, que tiene métodos de iteración internos 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 encargarse de su propia iteración.

es importante mantener la colección separada del puntero.el iterador apunta a un lugar específico de una colección y, por lo tanto, no es una parte integral de la colección.De esta manera, por ejemplo, puedes utilizar varios iteradores en la misma colección.

La desventaja de esta separación es que el iterador no se da cuenta de los cambios realizados en la colección que itera.por lo que no se puede cambiar la estructura de la colección y esperar que el iterador continúe su trabajo sin "quejas".

Utilizando el Iterator La interfaz permite que cualquier clase que implemente sus métodos actúe como iterador.La noción de 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 la forma requerida por la interfaz.Dado que las obligaciones contractuales deben cumplirse para ser una clase válida, otras clases que ven la clase implements la interfaz y, por lo tanto, estará tranquilo al saber que la clase tendrá ciertas funcionalidades.

En este ejemplo, en lugar de implementar los métodos (hasNext(), next(), remove()) en el LinkedList clase misma, la LinkedList La clase declarará que implements el Iterator interfaz, para que otros sepan que el LinkedList se puede utilizar como iterador.A su vez, el LinkedList La clase implementará los métodos del Iterator interfaz (como hasNext()), por lo que puede funcionar como un iterador.

En otras palabras, implementar una interfaz es una noción de programación orientada a objetos para que otros sepan que una determinada clase tiene lo necesario para ser lo que dice ser.

Esta noción se aplica 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 el Iterator interfaz que de hecho tendrá métodos que los iteradores deberían tener, como hasNext().

Además, cabe señalar que dado que Java no tiene herencia múltiple, se puede utilizar el uso de la interfaz 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 implementando una interfaz.Un ejemplo sería, si quisiera tener una subclase de la LinkedList clase llamada ReversibleLinkedList que podría iterar en orden inverso, puedo crear una interfaz llamada ReverseIterator y exigir que proporcione un previous() método.desde el LinkedList ya implementa Iterator, la nueva lista reversible habría implementado tanto Iterator y ReverseIterator interfaces.

Puede leer más sobre interfaces en ¿Qué es una interfaz? del tutorial de Java de Sun.

Se pueden utilizar varias instancias de un interator simultáneamente.Acérquese a ellos como cursores locales para los datos subyacentes.

POR CIERTO:favorecer las interfaces sobre las implementaciones concretas pierde el acoplamiento

Busque el patrón de diseño del iterador y aquí: http://en.wikipedia.org/wiki/Iterator

Porque es posible que esté iterando sobre algo que no es una estructura de datos.Digamos que tengo una aplicación en red que obtiene 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 Iterador.

Piense en ello como una parte clave de un buen diseño MVC.Los datos deben provenir del modelo (es decir,estructura de datos) a la Vista de alguna manera.El uso de un iterador como intermediario garantiza que la implementación del modelo nunca quede expuesta.Podría mantener una LinkedList en la memoria, extraer información de un algoritmo de descifrado o envolver llamadas JDBC.Simplemente no le importa a la vista, porque a la vista solo le importa la interfaz del Iterador.

Un artículo interesante que analiza los pros y los contras del uso de iteradores:

http://www.sei.cmu.edu/pacc/CBSE5/Sridhar-cbse5-final.pdf

Creo que es simplemente una buena práctica de OO.Puede tener código que trate con todo tipo de iteradores e incluso le brinde 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 el tipo de implementación que hay detrás.

Solo M2C, si no lo sabías:Puede evitar el uso directo de la interfaz del iterador en situaciones en las que el para cada bucle será suficiente.

En última instancia, porque Iterator captura una abstracción de control que es aplicable a una gran cantidad de estructuras de datos.Si está al tanto de su teoría de categorías fu, este artículo le dejará boquiabierto: La esencia del patrón iterador.

Bueno, parece que el primer punto permite que las aplicaciones de subprocesos múltiples (o de un solo subproceso si comete un error) no necesiten bloquear la colección por infracciones de concurrencia.En .NET, por ejemplo, no se puede enumerar y modificar una colección (o lista o cualquier IEnumerable) al mismo tiempo sin bloquear o heredar de IEnumerable y anular métodos (obtenemos excepciones).

Iterator simplemente agrega una forma común de repasar una colección de elementos.Una de las características interesantes es i.remove() en la que puedes eliminar elementos de la lista sobre la que estás iterando.Si simplemente intentara eliminar elementos de una lista, normalmente tendría efectos extraños o una excepción.

La interfaz es como un contrato para todas las cosas que la implementan.Básicamente estás diciendo...Se garantiza que cualquier cosa que implemente un iterador tendrá estos métodos que se comportarán de la misma manera.También puedes usarlo para pasar tipos de iteradores si eso es todo lo que te importa en tu código.(Puede que no te importe qué tipo de lista sea...solo desea pasar un iterador) Puede colocar todos estos métodos de forma independiente en las colecciones, pero no garantiza que se comporten igual o que incluso tengan el mismo nombre y firmas.

Los iteradores son uno de los muchos patrones de diseño disponibles en Java.Los patrones de diseño pueden considerarse como bloques de construcción, estilos y usos convenientes de su código/estructura.

Para leer más sobre el patrón de diseño Iterator, consulte este sitio web que habla sobre Iterator 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 recopilació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 realizan un procesamiento especial y devuelvan solo elementos especificados de la recopilación de datos.

Los iteradores se pueden utilizar contra cualquier tipo de colección.Le permiten definir un algoritmo frente a una colección de elementos independientemente de la implementación subyacente.Esto significa que puede procesar una lista, conjunto, cadena, archivo, matriz, etc.

Dentro de diez años, podrá cambiar la implementación de su Lista a una mejor implementación y el algoritmo seguirá funcionando sin problemas.

Iterator es útil cuando se trata de colecciones en Java.

Usar Para cada loop(Java1.5) para iterar sobre una colección, matriz o lista.

La interfaz java.util.Iterator se utiliza en Java Collections Framework para permitir la modificación de la colección mientras se sigue iterando a través de ella.Si solo desea iterar limpiamente sobre una colección completa, use un for-each en su lugar, pero una ventaja de los iteradores es la funcionalidad que obtiene:una operación remove() opcional, y aún mejor para la interfaz List Iterator, que también ofrece operaciones add() y set().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 con un for-each arrojaría una excepción ConcurrentModificationException, generalmente porque la colección se modifica 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 de encerrado, pueden modificar libremente la lista de matrices sin activar una medición de modificación concurrente. , a menos que cambie la lista al mismo tiempo (concurentemente) a través de los métodos set () add () o eliminar () de la clase ArrayList.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top