Sortir des boucles nestedes en Java

J’ai une construction de boucle nestede comme ceci:

for (Type type : types) { for (Type t : types2) { if (some condition) { // Do something and break... break; // Breaks out of the inner loop } } } 

Maintenant, comment puis-je sortir des deux boucles? J’ai examiné des questions similaires, mais aucune ne concerne spécifiquement Java. Je n’ai pas pu appliquer ces solutions car la plupart des gotos étaient utilisés.

Je ne veux pas mettre la boucle interne dans une méthode différente.

Mise à jour: je ne veux pas réexécuter les boucles, lorsque je suis rompu, j’ai terminé l’exécution du bloc de boucle.

    Comme les autres intervenants, je préférerais certainement mettre la boucle interne dans une méthode différente. Cette réponse montre simplement comment répondre aux exigences de la question.

    Vous pouvez utiliser break avec une étiquette pour la boucle externe. Par exemple:

     public class Test { public static void main(Ssortingng[] args) { outerloop: for (int i=0; i < 5; i++) { for (int j=0; j < 5; j++) { if (i * j > 6) { System.out.println("Breaking"); break outerloop; } System.out.println(i + " " + j); } } System.out.println("Done"); } } 

    Cela imprime:

     0 0 0 1 0 2 0 3 0 4 1 0 1 1 1 2 1 3 1 4 2 0 2 1 2 2 2 3 Breaking Done 

    Techniquement, la bonne réponse consiste à étiqueter la boucle externe. En pratique, si vous souhaitez quitter à tout moment dans une boucle interne, il serait préférable d’externaliser le code dans une méthode (méthode statique si nécessaire) et de l’appeler ensuite.

    Cela serait rentable pour la lisibilité.

    Le code deviendrait quelque chose comme ça:

     private static Ssortingng search(...) { for (Type type : types) { for (Type t : types2) { if (some condition) { // Do something and break... return search; } } } return null; } 

    Correspondant à l’exemple de la réponse acceptée:

      public class Test { public static void main(Ssortingng[] args) { loop(); System.out.println("Done"); } public static void loop() { for (int i = 0; i < 5; i++) { for (int j = 0; j < 5; j++) { if (i * j > 6) { System.out.println("Breaking"); return; } System.out.println(i + " " + j); } } } } 

    Vous pouvez utiliser un bloc nommé autour des boucles:

     search: { for (Type type : types) { for (Type t : types2) { if (some condition) { // Do something and break... break search; } } } } 

    Je n’utilise jamais d’étiquettes. Cela semble être une mauvaise pratique à prendre. Voici ce que je ferais:

     boolean finished = false; for (int i = 0; i < 5 && !finished; i++) { for (int j = 0; j < 5; j++) { if (i * j > 6) { finished = true; break; } } } 

    Vous pouvez utiliser des étiquettes:

     label1: for (int i = 0;;) { for (int g = 0;;) { break label1; } } 

    peut-être avec une fonction?

     public void doSomething(List types, List types2){ for(Type t1 : types){ for (Type t : types2) { if (some condition) { //do something and return... return; } } } } 

    Vous pouvez utiliser une variable temporaire:

     boolean outerBreak = false; for (Type type : types) { if(outerBreak) break; for (Type t : types2) { if (some condition) { // Do something and break... outerBreak = true; break; // Breaks out of the inner loop } } } 

    Selon votre fonction, vous pouvez également sortir / revenir de la boucle interne:

     for (Type type : types) { for (Type t : types2) { if (some condition) { // Do something and break... return; } } } 

    Si vous n’aimez pas les break et goto , vous pouvez utiliser un “traditionnel” pour la boucle à la place du for-in, avec une condition d’abandon supplémentaire:

     int a, b; bool abort = false; for (a = 0; a < 10 && !abort; a++) { for (b = 0; b < 10 && !abort; b++) { if (condition) { doSomeThing(); abort = true; } } } 

    Je devais faire une chose similaire, mais j’ai choisi de ne pas utiliser la boucle améliorée pour le faire.

     int s = type.size(); for (int i = 0; i < s; i++) { for (int j = 0; j < t.size(); j++) { if (condition) { // do stuff after which you want // to completely break out of both loops s = 0; // enables the _main_ loop to terminate break; } } } 

    Je préfère append une “sortie” explicite aux tests de boucle. Cela rend clair pour tout lecteur occasionnel que la boucle peut se terminer tôt.

     boolean earlyExit = false; for(int i = 0 ; i < 10 && !earlyExit; i++) { for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; } } 

    Solution Java 8 Stream :

     List types1 = ... List types2 = ... types1.stream() .flatMap(type1 -> types2.stream().map(type2 -> new Type[]{type1, type2})) .filter(types -> /**some condition**/) .findFirst() .ifPresent(types -> /**do something**/); 

    Vous pouvez rompre toutes les boucles sans utiliser aucune étiquette: et les drapeaux.

    C’est une solution délicate.

    La condition 1 est la condition utilisée pour rompre avec la boucle K et J. La condition 2 est la condition utilisée pour rompre avec la boucle K, J et I.

    Par exemple:

     public class BreakTesting { public static void main(Ssortingng[] args) { for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { for (int k = 0; k < 9; k++) { if (condition1) { System.out.println("Breaking from Loop K and J"); k = 9; j = 9; } if (condition2) { System.out.println("Breaking from Loop K, J and I"); k = 9; j = 9; i = 9; } } } } System.out.println("End of I , J , K"); } } 

    Pendant un certain temps, je pensais partager ce type de réponse pour ce type de question.

    Habituellement, de tels cas entrent dans une logique plus significative, disons une recherche ou une manipulation sur certains des objects “pour” itérés en question, donc j’utilise habituellement l’approche fonctionnelle:

     public Object searching(Object[] types) {//or manipulating List typesReferences = new ArrayList(); List typesReferences2 = new ArrayList(); for (Object type : typesReferences) { Object o = getByCriterion(typesReferences2, type); if(o != null) return o; } return null; } private Object getByCriterion(List typesReferences2, Object criterion) { for (Object typeReference : typesReferences2) { if(typeReference.equals(criterion)) { // here comes other complex or specific logic || typeReference.equals(new Object()) return typeReference; } } return null; } 

    Principaux inconvénients:

    • environ deux fois plus de lignes
    • plus de consommation de cycles de calcul, ce qui signifie qu’il est plus lent du sharepoint vue algorithmique
    • plus de travail de frappe

    Les pros:

    • le rapport plus élevé à la séparation des préoccupations en raison de la granularité fonctionnelle
    • le plus haut ratio de réutilisation et de contrôle de la logique de recherche / manipulation sans
    • les méthodes ne sont pas longues, elles sont donc plus compactes et plus faciles à comprendre
    • rapport subjectivement plus élevé de lisibilité

    Donc, il ne fait que traiter le cas via une approche différente.

    Fondamentalement, une question à l’auteur de cette question: que considérez-vous de cette approche?

    Méthode Best et Easy ..

     outerloop: for(int i=0; i<10; i++){ // here we can break Outer loop by break outerloop; innerloop: for(int i=0; i<10; i++){ // here we can break innerloop by break innerloop; } } 

    Si c’est à l’intérieur d’une fonction, pourquoi ne pas la retourner simplement:

     for (Type type : types) { for (Type t : types2) { if (some condition) { return value; } } } 

    Approche plutôt inhabituelle mais en termes de longueur de code ( pas de performance ), c’est la chose la plus simple que vous puissiez faire:

     for(int i = 0; i++; i < j) { if(wanna exit) { i = i + j; // if more nested, also add the // maximum value for the other loops } } 
     boolean broken = false; // declared outside of the loop for efficiency for (Type type : types) { for (Type t : types2) { if (some condition) { broken = true; break; } } if (broken) { break; } } 

    Je voulais répondre à cette question mais a été marquée comme un double qui m’empêche de poster aussi. Donc, l’afficher ici à la place!

    Si c’est une nouvelle implémentation, vous pouvez essayer de réécrire la logique sous forme d’instructions if-else_if-else.

     while(keep_going) { if(keep_going && condition_one_holds) { // code } if(keep_going && condition_two_holds) { // code } if(keep_going && condition_three_holds) { // code } if(keep_going && something_goes_really_bad) { keep_going=false; } if(keep_going && condition_four_holds) { // code } if(keep_going && condition_five_holds) { // code } } 

    Sinon, vous pouvez essayer de définir un indicateur lorsque cette condition spéciale s’est produite et vérifier cet indicateur dans chacune de vos conditions de boucle.

     something_bad_has_happened = false; while(something is true && !something_bad_has_happened){ // code, things happen while(something else && !something_bad_has_happened){ // lots of code, things happens if(something happened){ -> Then control should be returned -> something_bad_has_happened=true; continue; } } if(something_bad_has_happened) { // things below will not be executed continue; } // other things may happen here as well but will not be executed // once control is returned from the inner cycle } HERE! So, while a simple break will not work, it can be made to work using continue. 

    Si vous portez simplement la logique d’un langage de programmation à java et que vous voulez simplement faire fonctionner les choses, vous pouvez essayer d’utiliser des étiquettes.

    Demo for break , continue , label .

    Donc les mots-clés java se break et continue avoir une valeur par défaut, c’est la “Boucle la plus proche”, Toady quelques années après l’utilisation de Java, je viens de le recevoir!

    Il semble rare, mais utile.

     import org.junit.Test; /** * Created by cui on 17-5-4. */ public class BranchLabel { @Test public void test() { System.out.println("testBreak"); testBreak(); System.out.println("testBreakLabel"); testBreakLabel(); System.out.println("testContinue"); testContinue(); System.out.println("testContinueLabel"); testContinueLabel(); } /** testBreak a=0,b=0 a=0,b=1 a=1,b=0 a=1,b=1 a=2,b=0 a=2,b=1 a=3,b=0 a=3,b=1 a=4,b=0 a=4,b=1 */ public void testBreak() { for (int a = 0; a < 5; a++) { for (int b = 0; b < 5; b++) { if (b == 2) { break; } System.out.println("a=" + a + ",b=" + b); } } } /** testContinue a=0,b=0 a=0,b=1 a=0,b=3 a=0,b=4 a=1,b=0 a=1,b=1 a=1,b=3 a=1,b=4 a=2,b=0 a=2,b=1 a=2,b=3 a=2,b=4 a=3,b=0 a=3,b=1 a=3,b=3 a=3,b=4 a=4,b=0 a=4,b=1 a=4,b=3 a=4,b=4 */ public void testContinue() { for (int a = 0; a < 5; a++) { for (int b = 0; b < 5; b++) { if (b == 2) { continue; } System.out.println("a=" + a + ",b=" + b); } } } /** testBreakLabel a=0,b=0,c=0 a=0,b=0,c=1 * */ public void testBreakLabel() { anyName: for (int a = 0; a < 5; a++) { for (int b = 0; b < 5; b++) { for (int c = 0; c < 5; c++) { if (c == 2) { break anyName; } System.out.println("a=" + a + ",b=" + b + ",c=" + c); } } } } /** testContinueLabel a=0,b=0,c=0 a=0,b=0,c=1 a=1,b=0,c=0 a=1,b=0,c=1 a=2,b=0,c=0 a=2,b=0,c=1 a=3,b=0,c=0 a=3,b=0,c=1 a=4,b=0,c=0 a=4,b=0,c=1 */ public void testContinueLabel() { anyName: for (int a = 0; a < 5; a++) { for (int b = 0; b < 5; b++) { for (int c = 0; c < 5; c++) { if (c == 2) { continue anyName; } System.out.println("a=" + a + ",b=" + b + ",c=" + c); } } } } } 

    for (int j = 0; j < 5; j++) //inner loop doit être remplacée par for (int j = 0; j < 5 && !exitloops; j++) .

    Ici, dans ce cas, les boucles nestedes complètes doivent sortir si la condition est True . Mais si nous utilisons des exitloops uniquement dans la loop supérieure

      for (int i = 0; i < 5 && !exitloops; i++) //upper loop 

    Ensuite, la boucle interne continuera, car il n'y a pas de drapeau supplémentaire qui notifie la sortie de cette boucle interne.

    Exemple: si i = 3 et j=2 alors la condition est false . Mais dans la prochaine itération de la boucle interne j=3 alors la condition (i*j) devient 9 ce qui est true mais la boucle interne sera continue jusqu'à ce que j devienne 5 .

    Donc, il doit aussi utiliser des exitloops de exitloops pour les boucles internes.

     boolean exitloops = false; for (int i = 0; i < 5 && !exitloops; i++) { //here should exitloops as a Conditional Statement to get out from the loops if exitloops become true. for (int j = 0; j < 5 && !exitloops; j++) { //here should also use exitloops as a Conditional Statement. if (i * j > 6) { exitloops = true; System.out.println("Inner loop still Continues For i * j is => "+i*j); break; } System.out.println(i*j); } } 

    Comme la suggestion @ 1800 INFORMATION, utilisez la condition qui rompt la boucle interne en tant que condition sur la boucle externe:

     boolean hasAccess = false; for (int i = 0; i < x && hasAccess == false; i++){ for (int j = 0; j < y; j++){ if (condition == true){ hasAccess = true; break; } } } 

    Utilisez des étiquettes.

     INNER:for(int j = 0; j < numbers.length; j++) { System.out.println("Even number: " + i + ", break from INNER label"); break INNER; } 

    Reportez-vous à cet article

    Une autre solution, mentionnée sans exemple (elle fonctionne en code produit).

     try { for (Type type : types) { for (Type t : types2) { if (some condition #1) { // Do something and break the loop. throw new BreakLoopException(); } } } } catch (BreakLoopException e) { // Do something on look breaking. } 

    Bien sûr, BreakLoopException devrait être interne, privé et accéléré sans aucune trace de stack:

     private static class BreakLoopException extends Exception { @Override public StackTraceElement[] getStackTrace() { return new StackTraceElement[0]; } } 

    Vous pouvez effectuer les opérations suivantes:

    1. définir une variable locale sur false

    2. définir cette variable true dans la première boucle, quand vous voulez casser

    3. alors vous pouvez vérifier dans la boucle externe, que la condition soit définie ou non.

       boolean isBreakNeeded = false; for (int i = 0; i < some.length; i++) { for (int j = 0; j < some.lengthasWell; j++) { //want to set variable if (){ isBreakNeeded = true; break; } if (isBreakNeeded) { break; //will make you break from the outer loop as well } } 

    Dans certains cas, nous pouvons utiliser la boucle de manière efficace ici.

     Random rand = new Random(); // Just an example for (int k = 0; k < 10; ++k) { int count = 0; while (!(rand.nextInt(200) == 100)) { count++; } results[k] = count; } 

    Même créer un drapeau pour la boucle externe et vérifier que, après chaque exécution de la boucle interne peut être la réponse.

    Comme ça :

     for (Type type : types) { boolean flag=false; for (Type t : types2) { if (some condition) { // Do something and break... flag=true; break; // Breaks out of the inner loop } } if(flag) break; } 
     boolean condition = false; for (Type type : types) { for (int i = 0; i < otherTypes.size && !condition; i ++) { condition = true; // if your condition is satisfied } } 

    Utilisez la condition comme indicateur pour le traitement terminé. Ensuite, la boucle interne continue uniquement lorsque la condition n'a pas été remplie. Dans les deux cas, la boucle extérieure restra vide.

    Java n’a pas de fonctionnalité goto comme il y a en C ++. Mais encore, goto est un mot-clé réservé en Java. Ils pourraient l’implémenter à l’avenir. Pour votre question, la réponse est qu’il y a quelque chose appelé label dans Java auquel vous pouvez appliquer une instruction continue et break . Trouvez le code ci-dessous:

     public static void main(Ssortingng ...args) { outerLoop: for(int i=0;i<10;i++) { for(int j=10;j>0;j--) { System.out.println(i+" "+j); if(i==j) { System.out.println("Condition Fulfilled"); break outerLoop; } } } System.out.println("Got out of the outer loop"); } 

    Vous utilisez juste l’étiquette pour briser les boucles internes

     public class Test { public static void main(Ssortingng[] args) { outerloop: for (int i=0; i < 5; i++) { for (int j=0; j < 5; j++) { if (i * j > 6) { System.out.println("Breaking"); break outerloop; } System.out.println(i + " " + j); } } System.out.println("Done"); } } 

    Vérifiez si la boucle interne est sortie avec une instruction if, en vérifiant la variable de la boucle interne. Vous pouvez également créer une autre variable telle qu’un booléen pour vérifier si la boucle interne est sortie.

    Dans cet exemple, il utilise la variable de la boucle interne pour vérifier si elle est sortie:

     int i, j; for(i = 0; i < 7; i++){ for(j = 0; j < 5; j++) { if (some condition) { // Do something and break... break; // Breaks out of the inner loop } } if(j < 5){ // Checks if inner loop wasn't finished break; // Breaks out of the outer loop } }