2011-03-10 8 views
24

Para mi trabajo, tengo que desarrollar una pequeña aplicación Java que analiza archivos XML muy grandes (~ 300k líneas) para seleccionar datos muy específicos (usando Pattern), así que estoy tratando de optimizarlo un poco Me preguntaba qué era mejor entre estos 2 fragmentos:¿Qué es mejor? Múltiples instrucciones if, o una si tiene varias condiciones

if(boolean_condition && matcher.find(string)) 
{ 
    ... 
} 

O

if(boolean_condition) 
{ 
    if(matcher.find(string)) 
    { 
     ... 
    } 
} 

Más precisiones:

  • Estas sentencias if se ejecutan en cada iteración dentro de un bucle (~ 20k iteraciones)
  • El boolean_condition es un boolean calcu RELAClONADAS en cada iteración mediante una función externa
  • Si el boolean se establece en false, no necesito para probar la expresión regular para partidos

Gracias por su ayuda

+0

No hay una respuesta fácil. Consulte [este análisis SO] (http://stackoverflow.com/questions/1928712/how-to-split-up-complex-conditions-and-keep-short-circuit-evaluation) sobre el mismo tema. –

Respuesta

42

Una regla de oro sigo es a Evite anidar todo lo que pueda. Pero si es a costa de hacer que mi única condición sea demasiado compleja, no me importa anidarla.

Además, está utilizando el operador de cortocircuito &&. Entonces, si boolean es falso, ¡ni siquiera intentará hacer coincidir!

Así,

if(boolean_condition && matcher.find(string)) 
{ 
    ... 
} 

es el camino a seguir!

+0

¡Gracias! No estaba seguro del operador, si se configuró en falso, si la coincidencia se ejecutaría o no. – 3rgo

+9

Considera 'if (x! = Null && x.isY())'; si '&&' * no * cortocircuito la evaluación, eso explotaría en tu rostro el instante x == nulo. –

+1

¡Sí, de hecho! Pero tenía que estar seguro, así que pregunté – 3rgo

1

El primero. Intento evitar si anidando así, creo que es un código de estilo pobre/feo y el & & hará un cortocircuito y solo probará con matcher.find() si el valor booleano es verdadero.

3

Ambos caminos están bien, y la segunda condición no se probará si la primera es falsa.

Utilice el que hace que el código sea más legible y comprensible. Solo por dos condiciones, la primera es más lógica y legible. Puede que ya no sea así con 5 o 6 condiciones relacionadas con &&, || y !.

2

Java usa un cortocircuito para esos operadores booleanos, por lo que ambas variaciones son funcionalmente idénticas.Por lo tanto, si el boolean_condition es falso, no continuará con el

En última instancia, se trata de algo que resulta más fácil de leer y depurar, pero el anidamiento profundo puede ser difícil de manejar si termina con una gran cantidad de los apoyos al final

Una manera de mejorar la legibilidad, si la condición de ser más largo es simplemente dividirlo en varias líneas:

if(boolean_condition && 
    matcher.find(string)) 
{ 
    ... 
} 

la única opción en ese punto es si poner el & & y || al final de la línea anterior o al comienzo de la corriente.

13

Los dos métodos siguientes:

public void oneIf(boolean a, boolean b) 
{ 
    if (a && b) 
    { 
    } 
} 

public void twoIfs(boolean a, boolean b) 
{ 
    if (a) 
    { 
     if (b) 
     {  
     } 
    } 
} 

producen el mismo código de bytes exacto para el cuerpo del método por lo que no habrá ninguna diferencia de rendimiento que significa que es puramente una cuestión de estilo que se utiliza (personalmente prefiero la primer estilo).

+4

no se preguntaría si el método 'noIfs public void (Boolean, boolean b) {}' producido el mismo código de bytes también ;-) – Axel

+2

@Axel no, no lo hace (¡Acabo de comprobar!) No es sorprendente, el compilador de Java hace muy poca optimización, dejando que la JVM lo haga en tiempo de ejecución. – Jonathan

+0

Creo que el analizador tiene más trabajo por hacer en el segundo constructo, ya que tiene que averiguar si el enunciado siguiente es 'si' o algo más.Por otro lado, en la primera construcción, solo analizará la condición, y sabe que seguir es una parte de la condición. – kvaibhav

1

En términos de rendimiento, son lo mismo.

  • Pero incluso si no estaban

lo que es casi seguro que dominar el tiempo en este código es matcher.find(string) porque es una llamada a la función.

0

Tiendo a ver demasiados & & y || encadenados en una sopa lógica y son a menudo la fuente de errores sutiles.

Es muy fácil agregar otro & & o || a lo que crees que es el lugar correcto y romper la lógica existente.

Debido a esto como regla general trato de no utilizar ninguno de ellos para evitar la tentación de agregar más a medida que cambian los requisitos.

1

Si te gusta la conformidad a Sonar rule squid:S1066 debe colapsar si las declaraciones para evitar la advertencia, ya que afirma:

plegable "if" deberían fusionarse

Cuestiones relacionadas