2009-02-15 18 views
29

Tengo cuatro bucles foreach que se repiten en las colecciones y, en función de una condición, hacen algo. Aquí está el código que estoy escribiendo ahora:¿Cómo romper múltiples ciclos foreach?

boolean breakFlag = false; 
String valueFromObj2 = null; 
String valueFromObj4 = null; 
for(Object1 object1: objects){ 
    for(Object2 object2: object1){ 
    //I get some value from object2 
    valueFromObj2 = object2.getSomeValue(); 
    for(Object3 object3 : object2){ 
     for(Object4 object4: object3){ 
     //Finally I get some value from Object4. 
     valueFromObj4 = object4.getSomeValue(); 
     //Compare with valueFromObj2 to decide either to break all the foreach loop 
     breakFlag = compareTwoVariable(valueFromObj2, valueFromObj4); 
     if(breakFlag){break;} 
     }//fourth loop ends here 
     if(breakFlag){break;} 
    }//third loop ends here 
    if(breakFlag){break;} 
    }//second loop ends here 
    if(breakFlag){break;} 
}//first loop ends here 

El objeto principal (objetos en el código) proviene de un tercer proveedor de SDK partido, así que no puedo cambiar nada en esa parte. Quiero preguntarle a la comunidad stackoverflow si hay un mejor enfoque para romper los cuatro ciclos foreach. O si hay alguna otra forma de refactorizar este código para hacerlo más legible y mantenible. Gracias.

+0

Por cierto, es * por * no * foreach *. –

+3

No, el for (Object o: os) se conoce en realidad como foreach o iterator loop. – Esko

+0

La versión original tenía "foreach" en el código en sí. Gracias por editar – royalGhost

Respuesta

78

Utilice una etiqueta en el bucle más externo e incluya esta etiqueta en la instrucción break cuando desee saltar de todos los bucles. En el siguiente ejemplo, he modificado el código para utilizar la etiqueta OUTERMOST:

String valueFromObj2 = null; 
String valueFromObj4 = null; 
OUTERMOST: for(Object1 object1: objects){ 
    for(Object2 object2: object1){ 
    //I get some value from object2 
    valueFromObj2 = object2.getSomeValue(); 
    for(Object3 object3 : object2){ 
     for(Object4 object4: object3){ 
     //Finally I get some value from Object4. 
     valueFromObj4 = object4.getSomeValue(); 
     //Compare with valueFromObj2 to decide either to break all the foreach loop 
     if(compareTwoVariable(valueFromObj2, valueFromObj4)) { 
      break OUTERMOST; 
     } 
     }//fourth loop ends here 
    }//third loop ends here 
    }//second loop ends here 
}//first loop ends here 
+4

Esta es la respuesta correcta a mi pregunta. Pero reestructuré como otras personas sugirieron y moví la lógica a una función pequeña y usé "retorno". – royalGhost

+0

Use las funciones de etiqueta solo si no tiene otra solución. No es una buena práctica. – lucasddaniel

0

¿Lanzar una excepción y atraparla fuera de los bucles? Use algo que sea "considerado dañino"

Es un poco gracioso cuando la informática se pinta en una esquina ;-)

+3

"Informática" no se "pinta en una esquina". Pero a veces los programadores toman decisiones o suposiciones tempranas que limitan sus opciones más adelante. –

+2

Creo que soy gracioso. Los resultados pueden variar. – dwc

+0

Los resultados pueden variar. rofl. –

1

Una forma de romper, o contraer varias declaraciones (en realidad marcos de pila) es una excepción, pero esto no es recomendable, ya que realmente costoso para el tiempo de ejecución para desenrollar la pila y podría llevar a un comportamiento indefinido muy difícil de depurar, (tenga esto en cuenta).

De lo contrario, lo que recomiendo, vuelva a escribir ese código para poder salir del lazo de una manera elegante. Si no puede cambiar este código de ninguna otra manera, entonces tendrá que dar lugar a excepciones ...

+0

Java admite etiquetas, pero solo se pueden usar con sentencias break y continue. –

19

Extraiga todos los bucles de la función y utilice return.

+0

El código como se muestra no es agradable: la refacturación a lo largo de estas líneas sería mucho mejor. – Fortyrunner

+2

esta es la forma preferida sobre el uso de etiquetas de corte, a menos que sepa que es más claro usar break. – Chii

+0

Introducir un límite de método en un lugar arbitrario es "la forma preferida"? –

6

se puede utilizar una sentencia break etiquetado. Este tipo de ruptura termina una instrucción externa

Ver The break Statement

0

La solución sencilla es poner todo el proceso de búsqueda de un método y return tan pronto como usted tiene una respuesta.

Sin embargo, la forma abstracta de su código de muestra deja otras posibilidades en cuestión. Por ejemplo, ¿hay alguna manera de "indexar" parte del contenido (por ejemplo, usando Map instancias) para que no tenga que usar bucles de fuerza bruta?

2

Vea el Branching Statements Java Tutorial de la manera más fácil, utilizando una etiqueta. Puede etiquetar uno o todos los bucles para, luego use break o continue junto con esas etiquetas.

Una alternativa al uso de etiquetas es usar return en su lugar. Simplemente refactorice su código en una llamada a método para evitar la necesidad de usar etiquetas.

2

Su ejemplo es bastante genérico, por lo que es difícil decir lo que está pasando, pero obtengo un olor tan fuerte por el código que proporcioné que estoy forzado a pensar que tiene que haber otra manera de hacerlo completamente , probablemente a través de la refacturación de la estructura de datos real a algo más significativo.

¿Qué clase de lista es objects? ¿Qué otro dato (muy probablemente importante) contiene? Si no es demasiado complicado, te agradecería si me proporcionas un código más relevante ya que el refactorizador en mí se está mareando al ver ese montón de bucles.

Cuestiones relacionadas