2009-02-15 8 views
29

Ich habe vier foreach-Schleifen, die durch die Sammlungen iterieren und basierend auf einer Bedingung etwas tun. Hier ist der Code, den ich jetzt schreibe:Wie man mehrere foreach Schleife bricht?

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 

Das Hauptobjekt (Objekte im Code) stammt von einem Drittanbieter SDK, so kann ich nichts auf diesem Abschnitt ändern. Ich möchte die Stackoverflow-Community fragen, ob es einen besseren Ansatz gibt, alle vier foreach-Schleifen zu durchbrechen. Oder wenn es eine andere Möglichkeit gibt, diesen Code umzuformulieren, um ihn lesbarer und wartbarer zu machen. Vielen Dank.

+0

Btw, es ist * für * nicht * foreach *. –

+3

Nein, das for (Object o: os) ist eigentlich als Foreach oder Iterator-Schleife bekannt. – Esko

+0

Die ursprüngliche Version hatte "foreach" im Code selbst. Danke für die Bearbeitung. – royalGhost

Antwort

78

Verwenden Sie ein Etikett auf der äußersten Schleife und fügen Sie dieses Etikett in die Anweisung break ein, wenn Sie aus allen Schleifen springen möchten. Im Beispiel unten habe ich Ihren Code modifiziert, um das Etikett zu verwenden 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

Dies ist die richtige Antwort auf meine Frage. Aber ich refaktorierte wie andere Leute vorgeschlagen und bewegte die Logik zu einer kleinen Funktion und verwendet "Rückkehr". – royalGhost

+0

Label verwenden Funktionen nur, wenn Sie keine andere Lösung haben. Ist keine gute Übung. – lucasddaniel

0

Eine Ausnahme auslösen und außerhalb der Schleifen abfangen? Verwenden Sie etwas, das als "schädlich" angesehen wird?

Es ist ein bisschen komisch, wenn die Informatik selbst in eine Ecke malt ;-)

+3

"Informatik" malt sich nicht in eine Ecke. Aber manchmal treffen Programmierer frühe Entscheidungen oder Annahmen, die ihre Optionen später einschränken. –

+2

Ich denke, ich bin lustig. Ergebnisse können variieren. – dwc

+0

Ergebnisse können variieren. rofl. –

1

Eine Möglichkeit, mehrere Anweisungen (eigentlich Stack Frames) zu brechen, oder zu kollabieren, eine Ausnahme zu werfen, aber das, weil es ist nicht wirklich zu empfehlen teuer für die Laufzeit, um den Stapel abzuwickeln und es könnte zu wirklich unangenehm schwierig, undefined Verhalten zu debuggen, (dies zu beachten).

Ansonsten, was ich empfehle, schreiben Sie diesen Code um in der Lage, aus der Schleife in einer anmutigen Weise zu brechen. Wenn Sie diesen Code nicht anders ändern können, dann müssen Sie zu Ausnahmen führen ...

+0

Java unterstützt Labels, sie können jedoch nur mit Break- und Continue-Anweisungen verwendet werden. –

19

Extrahieren Sie alle Schleifen in die Funktion und verwenden Sie return.

+0

Der Code wie gezeigt ist nicht nett: Refactoring entlang dieser Linien wäre viel besser. – Fortyrunner

+2

Dies ist der bevorzugte Weg über die Verwendung von Break-Labels, es sei denn, Sie wissen, es ist klarer, Break zu verwenden. – Chii

+0

Die Einführung einer Methodengrenze an einem beliebigen Ort ist "der bevorzugte Weg"? –

6

Sie eine markierte break-Anweisung verwenden könnte. Diese Art von Bruch endet eine äußere Aussage

Siehe The break Statement

0

Die einfachste Lösung ist, den gesamten Suchprozess in einem Verfahren zu setzen und return, sobald Sie eine Antwort haben.

Die abstrakte Form Ihres Beispielcodes lässt jedoch einige andere Möglichkeiten in Frage. Gibt es beispielsweise eine Möglichkeit, einen Teil des Inhalts zu "indexieren" (z. B. mithilfe von Map Instanzen), sodass Sie keine Brute-Force-Schleifen verwenden müssen?

2

Sehen Sie die Branching Statements Java Tutorial für den einfachsten Weg, mit einem Etikett. Sie können beliebige oder alle for-Schleifen beschriften und dann break oder continue in Verbindung mit diesen Beschriftungen verwenden.

Eine Alternative zur Verwendung von Etiketten ist stattdessen return zu verwenden. Refactorieren Sie Ihren Code einfach in einen Methodenaufruf, um die Notwendigkeit der Verwendung von Labels zu umgehen.

2

Ihr Beispiel ist ziemlich generisch, so dass es schwer ist zu sagen, was los ist, aber ich bekomme so einen starken Code-Geruch aus dem Code, den Sie haben, dass ich denken muss, dass es eine andere Möglichkeit gibt, das Ding komplett zu machen , wahrscheinlich durch Refactoring der eigentlichen Datenstruktur zu etwas Sinnvollerem.

Welche Art von Liste objects ist? Was andere (sehr wahrscheinlich wichtig) Daten enthält es? Wenn es nicht zu viel Aufwand ist, würde ich mich freuen, wenn Sie relevanteren Code zur Verfügung stellen würden, da der Refaktor in mir völlig schwindlig wird, nur weil er diesen Haufen von Schleifen sieht.