2012-02-10 13 views
21

(Una pregunta para los que conocen bien la compilación y optimización trucos JVM ... :-)eficiencia bucle de Java ("para" frente a "foreach")

¿Hay alguna de la "para" y " foreach "patrones claramente superiores a los demás?

Considere los dos ejemplos siguientes:

public void forLoop(String[] text) 
{ 
    if (text != null) 
    { 
     for (int i=0; i<text.length; i++) 
     { 
      // Do something with text[i] 
     } 
    } 
} 

public void foreachLoop(String[] text) 
{ 
    if (text != null) 
    { 
     for (String s : text) 
     { 
      // Do something with s, exactly as with text[i] 
     } 
    } 
} 

Es forLoop más rápido o más lento que foreachLoop?

Suponiendo que en ambos casos la matriz text no necesitara ningún control de cordura, ¿hay un ganador claro o aún demasiado cerca para hacer una llamada?

EDITAR: Como se señala en algunas de las respuestas, el rendimiento debe ser idéntico para las matrices, mientras que el patrón "foreach" podría ser ligeramente mejor para los tipos de datos abstractos como una lista. Ver también this answer que discute el tema.

+0

La respuesta 256859 cubre mi pregunta, pero de alguna manera no apareció en las búsquedas que hice. ¡Gracias a todos! – PNS

Respuesta

55

De section 14.14.2 of the JLS:

lo contrario, la expresión necesariamente tiene un tipo de matriz, T []. Deje que L1 ... Lm sea la secuencia (posiblemente vacía) de las etiquetas que preceden inmediatamente a la declaración for mejorada. A continuación, el significado de la mejorada para la declaración está dada por la siguiente básica para la declaración:

T[] a = Expression; 
L1: L2: ... Lm: 
for (int i = 0; i < a.length; i++) { 
     VariableModifiersopt Type Identifier = a[i]; 
     Statement 
} 

En otras palabras, yo esperaría que para llegar a ser compilado para el mismo código.

Definitivamente hay un ganador claro: el bucle forzado mejorado es más legible. Esa debería ser su principal preocupación: solo debería considerar como micro optimizando este tipo de cosas cuando ha demostrado que la forma más legible no funciona tan bien como desea.

+10

+1 para enfatizar la importancia de la legibilidad/comprensibilidad! – jbranchaud

1

Dado que está utilizando un tipo array, la diferencia de rendimiento no importaría. Ellos terminarían dando el mismo rendimiento después de pasar por el embudo optimization.

Pero si está utilizando ADT como lista, entonces el forEachLoop es obviamente la mejor opción en comparación con múltiples llamadas get(i).

+1

más sí, no debe confiar en los detalles de 'optimización ', puede decepcionarse en cualquier momento. –

3

Debe elegir la opción que es más legible casi siempre, a menos que sepa que tiene un problema de rendimiento.

En este caso, yo diría que se garantiza que serán iguales.

La única diferencia es que comprueba más para text.length, que es probable que sea más lento, en lugar de más rápido.

También me aseguraría de que el texto nunca sea nulo de forma estática. p.ej. usando una anotación @NotNull. Es mejor detectar estos problemas en tiempo de compilación/compilación (y sería más rápido)

1

No existe una penalización de rendimiento para usar el bucle for-each, incluso para matrices. De hecho, puede ofrecer una ligera ventaja de rendimiento sobre un bucle ordinario en algunas circunstancias, ya que calcula el límite del índice de matriz solo una vez. Para más detalles, siga este post.

4

Puede escribir su propia prueba simple, que mida el tiempo de ejecución.

long start = System.currentTimeMillis(); 
forLoop(text); 
long end = System.currentTimeMillis(); 
long result = end - start; 

resultado es tiempo de ejecución.

+0

Aparentemente sí, pero en realidad hay muchos otros parámetros que afectan dicha medición (incluso el orden en que se ejecutan las pruebas) para considerarla confiable. – PNS

+2

Sí, las pruebas que miden el tiempo de ejecución y deben tener un cierto grado de validez nunca son "simples". – Bombe

+0

@PNS: Todavía es mejor medir (en una situación realista) de lo que es especular. Con la medición, solo se puede confundir un poco; con especulación, puede ir _simplemente_ mal. –