2009-02-15 15 views
29

Ho quattro cicli foreach che eseguono l'iterazione attraverso le raccolte e in base a una condizione fanno qualcosa. Ecco il codice che sto scrivendo adesso:Come interrompere più cicli 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 

Lo scopo principale (gli oggetti nel codice) proviene da un terzo fornitore di parti SDK, quindi non posso cambiare nulla su quella parte. Voglio chiedere alla community StackOverflow se esiste un approccio migliore per interrompere tutti e quattro i cicli foreach. O se esiste un altro modo per refactoring questo codice per renderlo più leggibile e mantenibile. Grazie.

+0

Btw, è * per * non * foreach *. –

+3

No, il for (Object o: os) è in realtà noto come ciclo foreach o iteratore. – Esko

+0

La versione originale aveva "foreach" nel codice stesso. Grazie per il montaggio. – royalGhost

risposta

78

Utilizzare un'etichetta sul ciclo più esterno e includere questa etichetta nell'istruzione break quando si desidera saltare da tutti i loop. Nell'esempio che segue, ho modificato il codice per utilizzare l'etichetta 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

Questa è la risposta corretta alla mia domanda. Ma, ho refactored come altre persone hanno suggerito e spostato la logica a una funzione piccola e ho usato "il ritorno". – royalGhost

+0

Usa etichetta Funziona solo se non si dispone di un'altra soluzione. Non è una buona pratica – lucasddaniel

0

Lanciare un'eccezione e afferrarla fuori dagli anelli? Usa qualcosa che è "considerato dannoso?"

è un po 'divertente quando l'informatica si dipinge in un angolo ;-)

+3

"Informatica" non "si dipinge in un angolo". Ma a volte i programmatori fanno scelte o assunzioni anticipate che limitano le loro opzioni in seguito. –

+2

Penso di essere divertente. I risultati possono variare – dwc

+0

I risultati possono variare. rofl. –

1

Un modo per rompere, o comprimere diverse dichiarazioni (in realtà impilare fotogrammi) è un'eccezione, ma questo non è consigliato perché in realtà costoso per il tempo di esecuzione per lo svolgimento dello stack e potrebbe portare a un comportamento indefinito difficile da debugare molto difficile (tenere presente questo).

Altrimenti, ciò che consiglio, riscrive quel codice per poter uscire dal loop in modo aggraziato. Se non puoi cambiare questo codice in nessun altro modo, allora dovrai fare delle eccezioni ...

+0

Java supporta le etichette, ma possono essere utilizzate solo con istruzioni break e continue. –

19

Estrarre tutti i loop nella funzione e usare return.

+0

Il codice mostrato non è bello: il refactoring lungo queste linee sarebbe molto meglio. – Fortyrunner

+2

questo è il modo preferito rispetto all'utilizzo delle etichette di interruzione, a meno che non si sappia che è più chiaro utilizzare l'interruzione. – Chii

+0

L'introduzione di un limite di metodo in un luogo arbitrario è "il modo preferito"? –

6

è possibile utilizzare un'istruzione break etichettata. Questo tipo di pausa termina una dichiarazione esterna

Vedi The break Statement

0

La soluzione semplice è quella di mettere l'intero processo di ricerca in un metodo e return non appena si ha una risposta.

Tuttavia, la forma astratta del codice di esempio lascia alcune altre possibilità in questione. Ad esempio, esiste un modo per "indicizzare" parte del contenuto (ad esempio utilizzando le istanze Map) in modo da non dover utilizzare loop brute-force?

2

Vedere il Branching Statements Java Tutorial per il modo più semplice, utilizzando un'etichetta. È possibile etichettare uno o tutti i loop for, quindi utilizzare break o continue insieme a tali etichette.

Un'alternativa all'utilizzo delle etichette è l'utilizzo di return. Basta ridimensionare il codice in una chiamata al metodo per evitare la necessità di utilizzare le etichette.

2

Il tuo esempio è piuttosto generico quindi è difficile dire cosa sta succedendo, ma sto ricevendo un odore così forte dal codice che hai fornito che sono costretto a pensare che ci debba essere un altro modo di fare la cosa interamente , molto probabilmente attraverso il refactoring della struttura dati effettiva a qualcosa di più significativo.

Che tipo di elenco è objects? Quali altri dati (molto probabilmente importanti) che contiene? Se non è una gran seccatura, sarei grato se tu avessi fornito un codice più pertinente dal momento che il refactorer in me sta diventando tutto stordito solo dal vedere quel mucchio di loop.