2010-10-07 9 views
6

Quiero saber si la evaluación de la condición se ejecuta en for y while bucles en Java cada vez que finaliza el ciclo de bucle.Java para la evaluación de bucle

Ejemplo:

int[] tenBig = new int[]{1,2,3,4,5,6,7,8,9,10}; 

for(int index = 0;index < tenBig.length;index++){ 
    System.out.println("Value at index: "+tenBig[index]); 
} 

¿El index < tenBig.length se ejecutan cada vez que el ciclo de bucle termina?

La suposición y la experiencia me dicen que sí.

Sé que en este ejemplo el tenBig.length es una constante, por lo que no habrá un impacto en el rendimiento.

Pero supongamos que la operación de condición lleva mucho tiempo en un caso diferente. Sé que lo más lógico es asignar el tenBig.length a una variable.

Todavía quiero estar seguro de que se evalúa siempre.

+1

Sé que es el caso en C++. ¿Pero es para Java? – Koekiebox

+0

En su ejemplo, la parte media del for se evaluará 11 veces. Una vez que corrige la ortografía de 'longitud' para que realmente se compile, eso es. – Powerlord

Respuesta

9

Sí, lógicamente evaluará la totalidad del operando intermedio en cada iteración del ciclo. En los casos en que el JIT lo sabe mejor, por supuesto, puede hacer cosas inteligentes (incluso eliminando potencialmente la verificación de límites de la matriz dentro del bucle, en función de las condiciones del bucle).

Tenga en cuenta que para los tipos que el JIT desconoce, es posible que no pueda optimizar específicamente de esta manera, pero aún puede alinear cosas como obtener size() de ArrayList<T>.

Por último, en general, prefiero el ciclo mejorado para facilitar la lectura:

for (int value : tenBig) { 
    ... 
} 

Por supuesto, eso es suponiendo que no es necesario el índice por otras razones.

+1

El bucle for mejorado tiene una mejora notable: la expresión ('tenBig' en su caso) solo se evalúa una vez, según el JLS. –

+0

Lo único que no me gusta del bucle "mejorado" es que no verifica valores nulos. En otras palabras, si el objeto tenBig es nulo, se lanza una NullPointerException, lo cual tiene sentido, pero hubiera sido increíble si el objeto se marca previamente con nulo. – Koekiebox

+5

@Koekiebox: ¿Qué crees que debería hacer en esa situación? Trátelo como una colección vacía? Personalmente, creo que un NPE es el resultado correcto aquí. –

3

Sí, la expresión se debe evaluar para cada iteración del ciclo para determinar si permanecer dentro del ciclo o continuar la ejecución del programa.

Recuerde que puede hacer cosas como esta:

for(int a = 0, z = 26; a < z; a++, z--){ 
    // Do some work 
} 

En ese caso, ambos lados de la expresión va a cambiar y debe ser evaluado para cada iteración.

y tienes razón, si usted tiene cálculos en la condición de bucle que se puede mover a una variable independiente, usted debe hacer lo siguiente:

for(int i = 0; i < ((someCount/2) * 21.6); i++){ 
} 

fácilmente podría ser:

int maxVal = (someCount/2) * 21.6; 

for(int i=0; i < maxVal; i++){ 
{ 
0

¿Pregunta si el compilador almacena en caché el valor de tenBig.length ya que sabe que no cambiará durante el ciclo? O pregunta si el compilador sabe automáticamente que no es necesario evaluar el índice de expresión completo < tenBig.length durante las siguientes 9 veces.

6

Sí. Específicamente, la parte de condición se ejecuta antes de cada cuerpo de bucle. Por lo tanto, es muy posible que nunca ingrese al cuerpo del bucle.

Así que tomar su ejemplo:

for(int index = 0;index < tenBig.lenght;index++) { 
    /* ...body... */ 
} 

Ésta es la lógica (no literal) equivalente:

int index = 0; 
while (index < tenBig.length) { // happens on each loop 
    /* ...body... */ 

    index++; 
} 
0

Esto va a ser ejecutado cada vez que se entra en el bucle, incluyendo la última evaluación que se índice de rendimiento < longitud = falso. Aparte de esto, aunque la longitud de diezBig es const, el bucle siempre accederá a esta propiedad por lo que sería ideal asignarlo a una variable (aunque no es una ganancia de velocidad razonable en su ejemplo).

1

Si la expresión condicional es un loop invariant y se está ejecutando en modo JIT, se pueden realizar optimizaciones de bucle como Loop-invariant code motion.

Pero cuando se ejecuta en el modo interpretado, I supongo no hay mucha optimización para hacer.

1

index < tenBig.length se ejecutarán antes de cada ciclo de ciclo.

public static void main(String[] args) { 
     int[] tenBig = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 

     for (int index = 0; isEvaluated() && index < tenBig.length; index++) { 
      System.out.println("Value at index: " + tenBig[index]); 
     } 
    } 

    public static boolean isEvaluated() { 
     System.out.println("evaluated"); 
     return true; 
    } 

Se imprimirá "evaluated" justo antes de los ciclos de aperturas. Y una vez más antes de que el bucle termine.

Cuestiones relacionadas