Iterator vs para

En una entrevista, me preguntaron ¿cuál es la ventaja de usar iterator usando for loop o cuál es la ventaja de utilizarlo para iterar?

¿Puede algún cuerpo responder esto para que en el futuro Si me enfrento a una pregunta similar, entonces pueda responder eso

En primer lugar, hay 2 tipos de ciclos for, que se comportan de manera muy diferente. Uno usa índices:

 for (int i = 0; i < list.size(); i++) { Thing t = list.get(i); ... } 

Este tipo de ciclo no siempre es posible. Por ejemplo, las listas tienen índices, pero los conjuntos no, porque son colecciones desordenadas.

El otro, el ciclo foreach usa un iterador detrás de escena:

 for (Thing thing : list) { ... } 

Esto funciona con todo tipo de colección Iterable (o matriz)

Y finalmente, puede usar un Iterador, que también funciona con cualquier Iterable:

 for (Iterator it = list.iterator(); it.hasNext(); ) { Thing t = it.next(); ... } 

Entonces, de hecho, tienes 3 bucles para comparar.

Puede compararlos en términos diferentes: rendimiento, legibilidad, propensión a errores, capacidad.

Un iterador puede hacer cosas que un bucle Foreach no puede hacer. Por ejemplo, puede eliminar elementos mientras itera, si el iterador lo admite:

 for (Iterator it = list.iterator(); it.hasNext(); ) { Thing t = it.next(); if (shouldBeDeleted(thing) { it.remove(); } } 

Las listas también ofrecen iteradores que pueden iterar en ambas direcciones. Un bucle foreach solo itera desde el principio hasta el final.

Pero un iterador es más peligroso y menos legible. Cuando un bucle foreach es todo lo que necesita, es la solución más legible. Con un iterador, podría hacer lo siguiente, que sería un error:

 for (Iterator it = list.iterator(); it.hasNext(); ) { System.out.println(it.next().getFoo()); System.out.println(it.next().getBar()); } 

Un bucle foreach no permite que ocurra tal error.

El uso de índices para acceder a elementos es ligeramente más eficiente con colecciones respaldadas por una matriz. Pero si cambias de opinión y utilizas LinkedList en lugar de ArrayList, de repente el rendimiento será horrible, porque cada vez que list.get(i) a list.get(i) , la lista enlazada tendrá que recorrer todos sus elementos hasta el ith. Un iterador (y por lo tanto el bucle foreach) no tiene este problema. Siempre utiliza la mejor manera posible de recorrer los elementos de la colección determinada, porque la colección en sí tiene su propia implementación Iterator.

Mi regla general es: use el ciclo foreach, a menos que realmente necesite las capacidades de un iterador. Solo usaría for loop con índices con matrices, cuando necesito acceder al índice dentro del ciclo.

Ventaja de Iterator:

  • Posibilidad de eliminar elementos de colecciones.
  • Posibilidad de avanzar y retroceder utilizando next() y previous() .
  • Posibilidad de verificar si hay más elementos o no utilizando hasNext() .

Loop fue diseñado solo para iterar sobre una Collection , por lo que si solo desea iterar sobre una Collection , es mejor usar un bucle como for-Each , pero si desea más de eso, puede usar Iterator.

si accede a los datos por número (por ejemplo, “i”), es rápido cuando utiliza una matriz. porque va directamente al elemento

Pero, otra estructura de datos (por ejemplo, árbol, lista), necesita más tiempo, porque comienza desde el primer elemento hasta el elemento objective. cuando usas list. Necesita tiempo O (n). entonces, es ser lento.

si usa el iterador, el comstackdor sabe dónde se encuentra. entonces necesita O (1) (porque, comienza desde la posición actual)

finalmente, si usa solo una matriz o estructura de datos que soporte el acceso directo (por ejemplo, arraylist en java). “a [i]” es bueno. pero, cuando usas otra estructura de datos, el iterador es más eficiente

La principal diferencia entre Iterator y el clásico para bucle, aparte de la obvia de tener o no tener acceso al índice del artículo que está iterando, es que al usar Iterator abstrae el código del cliente de la implementación de la colección subyacente, permítame elaborar.

Cuando su código usa un iterador, ya sea en esta forma

 for(Item element : myCollection) { ... } 

esta forma

 Iterator iterator = myCollection.iterator(); while(iterator.hasNext()) { Item element = iterator.next(); ... } 

o esta forma

 for(Iterator iterator = myCollection.iterator(); iterator.hasNext(); ) { Item element = iterator.next(); ... } 

Lo que dice el código es “No me importa el tipo de colección y su implementación, me importa que pueda iterar a través de sus elementos”. Lo cual suele ser el mejor enfoque, ya que hace que su código esté más desacoplado.

Por otro lado, si está utilizando el clásico para bucle, como en

 for(int i = 0; i < myCollection.size(); i++) { Item element = myCollection.get(i); ... } 

Su código dice: necesito saber el tipo de colección, porque necesito iterar a través de sus elementos de una manera específica, posiblemente voy a verificar nulos o calcular algún resultado según el orden de iteración. Lo que hace que su código sea más frágil, porque si en algún momento cambia el tipo de colección que recibe, tendrá un impacto en la forma en que funciona su código.

En resumen, la diferencia no se trata tanto de la velocidad, o el uso de la memoria, se trata más de desacoplamiento de su código para que sea más flexible para hacer frente a los cambios.