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 contenidaEl 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 deIterable
, entonces permítame ser el tipo de la expresión Expresión.iterator()
. El enunciado mejoradofor
es equivalente a una declaración básicafor
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 queL1 ... Lm
sea la secuencia (posiblemente vacía) de las etiquetas que preceden inmediatamente a la declaraciónfor
mejorada. Entonces, el significado de la declaración for mejorada viene dada por la siguiente declaración básicafor
:
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.