for example ejemplo java performance loops foreach premature-optimization

java - example - jsp for each list



Eficacia de Java Foreach (6)

Creo que es un compilador optimizado para ejecutarse solo una vez por entrada de bucle.

Tengo algo como esto:

Map<String, String> myMap = ...; for(String key : myMap.keySet()) { System.out.println(key); System.out.println(myMap.get(key)); }

Entonces, ¿se myMap.keySet() una vez en el ciclo foreach ? Creo que sí, pero quiero tu opinión.

Me gustaría saber si el uso de foreach de esta manera ( myMap.keySet() ) tiene un impacto en el rendimiento o es equivalente a esto:

Set<String> keySet = myMap.keySet(); for (String key : keySet) { ... }


La respuesta está en la Especificación del lenguaje Java, no es necesario descompilar :) Esto es lo que podemos leer sobre la declaración mejorada para :

La declaración mejorada para tiene la forma:

EnhancedForStatement: for ( VariableModifiersopt Type Identifier: Expression) Statement

La expresión debe tener un tipo Iterable o bien debe ser de un tipo de matriz (§10.1), o se produce un error en tiempo de compilación.

El alcance de una variable local declarada en la parte FormalParameter de una instrucción for forzada (§14.14) es la declaración contenida

El significado de la declaración mejorada está dada por la traducción en una declaración básica for .

Si el tipo de Expression es un subtipo de Iterable , entonces permítame ser el tipo de la expresión Expresión. iterator() . El enunciado mejorado for es equivalente a una declaración básica for el formulario:

for (I #i = Expression.iterator(); #i.hasNext(); ) { VariableModifiersopt Type Identifier = #i.next(); Statement }

Donde #i es un identificador generado por el compilador que es distinto de cualquier otro identificador (generado por el compilador o de otro modo) que esté dentro del alcance (§6.3) en el punto donde ocurre la declaración for forzada.

De 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. Entonces, el significado de la declaración for mejorada viene dada por la siguiente declaración básica for :

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

Donde a y yo somos identificadores generados por el compilador que son distintos de cualquier otro identificador (generado por el compilador o de otra manera) que están en el alcance en el punto donde ocurre la declaración for forzada.

En su caso, myMap.keySet() devuelve un subtipo de Iterable por lo que su declaración mejorada es equivalente a la siguiente declaración básica for :

for (Iterator<String> iterator = myMap.keySet().iterator(); iterator.hasNext();) { String key = iterator.next(); System.out.println(key); System.out.println(myMap.get(key)); }

Y myMap.keySet() se llama así solo una vez.


Sí, se llama solo de una u otra forma


Si quiere estar absolutamente seguro, compilarlo en ambos sentidos y descompilarlo y comparar. Hice esto con la siguiente fuente:

public void test() { Map<String, String> myMap = new HashMap<String, String>(); for (String key : myMap.keySet()) { System.out.println(key); System.out.println(myMap.get(key)); } Set<String> keySet = myMap.keySet(); for (String key : keySet) { System.out.println(key); System.out.println(myMap.get(key)); } }

y cuando descompilé el archivo de clase con Jad , obtengo:

public void test() { Map myMap = new HashMap(); String key; for(Iterator iterator = myMap.keySet().iterator(); iterator.hasNext(); System.out.println((String)myMap.get(key))) { key = (String)iterator.next(); System.out.println(key); } Set keySet = myMap.keySet(); String key; for(Iterator iterator1 = keySet.iterator(); iterator1.hasNext(); System.out.println((String)myMap.get(key))) { key = (String)iterator1.next(); System.out.println(key); } }

Así que ahí está tu respuesta. Se llama una vez con forma for-loop.


Solo se llama una vez. De hecho, usa un iterador para hacer el truco.

Además, en tu caso, creo que deberías usar

for (Map.Entry<String, String> entry : myMap.entrySet()) { System.out.println(entry.getKey()); System.out.println(entry.getValue()); }

para evitar buscar en el mapa cada vez.


keySet() se llama solo una vez. El "bucle Iterable mejorado" se basa en la interfaz Iterable , que utiliza para obtener un Iterator , que luego se utiliza para el bucle. Ni siquiera es posible iterar sobre un Set de ninguna otra manera, ya que no hay ningún índice ni nada por el cual pueda obtener elementos individuales.

Sin embargo, lo que realmente debería hacer es abandonar por completo este tipo de problemas de micro-optimización: si alguna vez tiene problemas reales de rendimiento, existe la probabilidad de que sea algo que nunca había pensado por sí solo.