recorrer - La forma más rápida de iterar una matriz en Java: variable de bucle vs mejorada para instrucción
recorrer lista en java (6)
Esta pregunta ya tiene una respuesta aquí:
En Java, ¿es más rápido iterar a través de una matriz a la vieja usanza,
for (int i = 0; i < a.length; i++)
f(a[i]);
O usando la forma más concisa,
for (Foo foo : a)
f(foo);
Para una ArrayList, ¿la respuesta es la misma?
Por supuesto, para la gran mayoría del código de la aplicación, la respuesta es que no hace una diferencia perceptible por lo que la forma más concisa se debe utilizar para la legibilidad. Sin embargo, el contexto que estoy viendo es el cálculo técnico de trabajo pesado, con operaciones que deben realizarse miles de millones de veces, por lo que incluso una pequeña diferencia de velocidad podría llegar a ser significativa.
Aún más rápido es usar ParallelArray del marco fork-join (si tiene un conjunto de datos lo suficientemente grande).
En una matriz, o colección RandomAccess puede obtener un pequeño aumento en la velocidad al hacer:
List<Object> list = new ArrayList<Object>();
for (int i=0, d=list.size(); i<d; i++) {
something(list.get(i));
}
Pero no me preocuparía en general. Las optimizaciones como esta no harán una diferencia de más del 0.1% en su código. Intenta invocar java con -prof para ver dónde está gastando realmente tu código.
Esto cae directamente en el campo de la micro-optimization . Realmente no importa. Estilísticamente, siempre prefiero el segundo porque es más conciso, a menos que necesites el contador de bucle para otra cosa. Y eso es mucho más importante que este tipo de micro-optimización : legibilidad.
Dicho esto, para una ArrayList no habrá mucha diferencia, pero una LinkedList será mucho más eficiente con la segunda.
Mídelo. La respuesta a todas las preguntas de rendimiento puede depender de la versión de VM, el procesador, la velocidad de memoria, las memorias caché, etc. Por lo tanto, debe medirla para su plataforma en particular.
Personalmente preferiría la segunda variante, porque la intención es más clara. Si el rendimiento se convierte en un problema, puedo optimizarlo más tarde de todos modos, si ese código es realmente importante para el rendimiento de toda la aplicación.
Para una LinkedList:
for(ClassOfElement element : listOfElements) {
System.out.println(element.getValue());
}
Fue respondido antes:
¿Hay una diferencia de rendimiento entre un bucle for y un bucle for-each?
Si está recorriendo una matriz, no debería importar: de todos modos, el bucle forzado mejorado usa accesos a la matriz.
Por ejemplo, considere este código:
public static void main(String[] args)
{
for (String x : args)
{
System.out.println(x);
}
}
Cuando descompilamos con javap -c Test
obtenemos (para el método main
):
public static void main(java.lang.String[]);
Code:
0: aload_0
1: astore_1
2: aload_1
3: arraylength
4: istore_2
5: iconst_0
6: istore_3
7: iload_3
8: iload_2
9: if_icmpge 31
12: aload_1
13: iload_3
14: aaload
15: astore 4
17: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
20: aload 4
22: invokevirtual #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
25: iinc 3, 1
28: goto 7
31: return
Ahora cámbialo para usar un acceso explícito a la matriz:
public static void main(String[] args)
{
for (int i = 0; i < args.length; i++)
{
System.out.println(args[i]);
}
}
Esto se descompila a:
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: aload_0
4: arraylength
5: if_icmpge 23
8: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_0
12: iload_1
13: aaload
14: invokevirtual #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
17: iinc 1, 1
20: goto 2
23: return
Hay un poco más de código de configuración en el bucle for mejorado, pero básicamente están haciendo lo mismo. No hay iteradores involucrados. Además, esperaría que se JITted a un código aún más similar.
Sugerencia: si realmente crees que podría marcar una diferencia significativa (lo que solo sucedería si el cuerpo del ciclo es absolutamente minúsculo), entonces debes compararlo con tu aplicación real. Esa es la única situación que importa.