Diferencia entre mover un iterador hacia adelante con una instrucción y una sentencia while

StackOverflow https://stackoverflow.com/questions/515562

Pregunta

Cuando uso un iterador de objetos utilizo un while (como está escrito en todos los libros de aprendizaje de Java, como Pensando en Java de Bruce Eckel):

Iterator it=...

while(it.hasNext()){
    //...
}

pero en algún momento vi que en lugar de utilizar a alguien bucle for

Iterator it=...
for (Iterator it=...; it.hasNext();){
    //...
}

No me' entiendo esta elección:

  • I uso el bucle for cuando tengo una colección con secuencia ordinal (como array) o con una regla especial para el paso (declara generalmente como un incremento simple counter++).
  • Yo uso el while cuando el bucle termina con I have'nt esta limitaciones, pero sólo una condición lógica para la salida.

Es una cuestión de estilo de codificación sin otra causa o existe alguna otra lógica (rendimiento, por ejemplo) que yo no' sé?

Gracias por todos los comentarios

¿Fue útil?

Solución

La sintaxis correcta para el bucle es:

for (Iterator it = ...; it.hasNext(); ){
    //...
}

(La declaración anterior en el código es superfluo, así como el punto y coma adicional en el encabezado de bucle.)

Si usted utiliza esta sintaxis o la while bucle es una cuestión de gusto, tanto a traducir exactamente lo mismo. La sintaxis genérica del bucle for es:

for (<init stmt>; <loop cond>; <iterate stmt>) { <body>; }

que es equivalente a:

<init stmt>;
while (<loop cond>) { <body>; <iterate stmt>; }

Editar En realidad, las dos formas anteriores no son totalmente equivalentes, si (como en la pregunta) la variable se declara con la declaración de inicio. En este caso, habrá una diferencia en el alcance de la variable iterador. Con el bucle, el alcance es limitado al bucle en sí, en el caso del bucle, mientras que, sin embargo, el alcance se extiende hasta el final del bloque de encerramiento (sin gran sorpresa, ya que la declaración está fuera del bucle).

Además, como otros han señalado, en las últimas versiones de Java, no es una notación abreviada para el bucle for:

for (Iterator<Foo> it = myIterable.iterator(); it.hasNext(); ) {
    Foo foo = it.next();
    //...
}

puede escribirse como:

for (Foo foo : myIterable) {
    //...
}

Con este formulario, por supuesto pierde la referencia directa al repetidor, que es necesario, por ejemplo, si desea eliminar elementos de la colección, mientras que la iteración.

Otros consejos

Es sólo una cosa de estilo y al igual que yo prefiero el bucle cuando se utiliza algo con un índice. Si está utilizando Java 5 se debe utilizar, por supuesto, un bucle foreach sobre la colección de todas formas:

Collection<String> someCollection = someCollectionOfString();
for (String element : someCollection) {
....
}

El propósito de declarar la Iterator dentro del bucle for es a minimizar el alcance de las variables , que es una buena práctica.

Cuando se declara la <=> fuera del bucle, entonces la referencia sigue siendo válida / viva después del bucle finaliza. 99,99% de las veces, no es necesario seguir utilizando el <=> una vez que el bucle se completa, por lo que un estilo de este tipo puede conducir a errores como este:

//iterate over first collection
Iterator it1 = collection1.iterator();
while(it1.hasNext()) {
   //blah blah
}

//iterate over second collection
Iterator it2 = collection2.iterator();
while(it1.hasNext()) {
   //oops copy and paste error! it1 has no more elements at this point
}

No hay mucha diferencia entre estos dos métodos, que no sea la primera se acuerda el valor de it después del bucle. El segundo enfoque, probablemente, genera un error, porque redeclare la variable dentro del bucle.

En realidad hay un tercer método para esto, también. En lugar de escribir por ejemplo.

for (Iterator<SomeObject> it = foo.iterator(); it.hasNext();) {
  SomeObject so = foo.next();
}

Puede escribir más a menudo

for (SomeObject so: foo) {...}

Estos dos iguales a la misma cosa ...

Las personas pueden usar la explícita ( 'viejo estilo') para el bucle simplemente porque se siente más limpio para ellos, tal vez no se han adaptado a la nueva sintaxis todavía (que yo personalmente creo que es mucho más limpio).

Una ventaja específica real de la más larga para bucle constructo es que usted tiene una referencia a la iterador y así puede llamar a métodos en él otros entonces next(). En particular, hasNext() a menudo puede ser útil para llamar - imaginar si desea imprimir una lista de cadenas separadas por comas:

StringBuilder sb = new StringBuilder();
for (Iterator it=...; it.hasNext();){
   sb.append(it.next());
   if (it.hasNext())
      sb.append(", ");
}

Es sólo para distinguir el "este es el último" caso como éste si se utiliza la más prolija de bucle.

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