Comment sortir des boucles imbriquées en Java?


J'ai une construction de boucle imbriquée 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 ne pouvais pas appliquer ces solutions car la plupart des gotos 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, lors de la rupture, j'ai terminé l'exécution du bloc de boucle.

Author: Steve Chambers, 2009-05-20

30 answers

Comme les autres répondeurs, je préférerais certainement mettre la boucle interne dans une méthode différente. Cette réponse montre simplement comment les exigences de la question peuvent être satisfaites.

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

public class Test {
    public static void main(String[] 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");
    }
}

Ceci 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
 2117
Author: Jon Skeet, 2018-04-20 17:11:39

Techniquement, la bonne réponse est d'étiqueter la boucle externe. En pratique, si vous voulez quitter à tout moment à l'intérieur d'une boucle interne, vous feriez mieux d'externaliser le code dans une méthode (une méthode statique si nécessaire), puis de l'appeler.

Cela serait payant pour la lisibilité.

Le code deviendrait quelque chose comme ça:

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

Correspondant à l'exemple pour la réponse acceptée:

 public class Test {
    public static void main(String[] 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);
            }
        }
    }
}
 372
Author: Zo72, 2012-06-03 10:31:41

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;
            }
        }
    }
}
 191
Author: Joey, 2009-05-20 09:12:12

Je n'utilise jamais d'étiquettes. Cela semble être une mauvaise pratique à adopter. 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;
        }
    }
}
 116
Author: Elle Mundy, 2014-08-04 17:18:10

Vous pouvez utiliser des étiquettes:

label1: 
for (int i = 0;;) {
    for (int g = 0;;) {
      break label1;
    }
}
 81
Author: simon622, 2018-04-20 16:30:26

Peut-être avec une fonction?

public void doSomething(List<Type> types, List<Type> types2){
  for(Type t1 : types){
    for (Type t : types2) {
      if (some condition) {
         //do something and return...
         return;
      }
    }
  }
}
 32
Author: Fortega, 2009-05-20 12:25:57

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 quitter / revenir de la boucle intérieure:

for (Type type : types) {
    for (Type t : types2) {
         if (some condition) {
             // Do something and break...
             return;
         }
    }
}
 15
Author: Miguel Ping, 2009-05-20 09:11:59

Si vous n'aimez pas break s et goto s, vous pouvez utiliser une boucle for" traditionnelle " à 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;
        }
    }
}
 10
Author: zord, 2013-12-21 22:56:34

J'avais besoin de faire une chose similaire, mais j'ai choisi de ne pas utiliser la boucle for 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;
        }
    }
}
 9
Author: Swifty McSwifterton, 2016-11-10 08:54:50

Je préfère ajouter un "exit" explicite aux tests de boucle. Il permet à 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; }
}
 7
Author: ddyer, 2018-04-20 16:33:33

Java 8 Stream solution:

List<Type> types1 = ...
List<Type> types2 = ...

types1.stream()
      .flatMap(type1 -> types2.stream().map(type2 -> new Type[]{type1, type2}))
      .filter(types -> /**some condition**/)
      .findFirst()
      .ifPresent(types -> /**do something**/);
 5
Author: Igor Rybak, 2018-04-20 17:46:58

Vous pouvez rompre toutes les boucles sans utiliser d'étiquette: et de drapeaux.

C'est juste une solution délicate.

Ici condition1 est la condition qui est utilisée pour rompre la boucle K et J. Et condition2 est la condition qui est utilisée pour rompre la boucle K, J et I.

Par exemple:

public class BreakTesting {
    public static void main(String[] 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");
    }
}
 4
Author: Hitendra Hckr, 2015-04-25 22:44:38

Plutôt depuis longtemps je pensais partager ce type de réponse pour ce type de question.

Habituellement, de tels cas entrent dans le cadre d'une logique plus significative, disons une recherche ou une manipulation sur certains des objets " for " itérés en question, donc j'utilise généralement l'approche fonctionnelle:

public Object searching(Object[] types) {//or manipulating
    List<Object> typesReferences = new ArrayList<Object>();
    List<Object> typesReferences2 = new ArrayList<Object>();

    for (Object type : typesReferences) {
        Object o = getByCriterion(typesReferences2, type);
        if(o != null) return o; 
    }
    return null;
}
private Object getByCriterion(List<Object> 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 point de vue algorithmique
  • plus travail de dactylographie

Les avantages:

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

Il s'agit donc simplement de gérer le cas via une approche différente.

Fondamentalement une question à l'auteur de ce question: que pensez-vous de cette approche?

 4
Author: Oleksii Kyslytsyn, 2016-01-28 19:14:59

Si c'est à l'intérieur d'une fonction, pourquoi ne le retournez-vous pas:

for (Type type : types) {
    for (Type t : types2) {
         if (some condition) {
            return value;
         }
    }
}
 3
Author: Chit Khine, 2016-08-25 11:25:58

Meilleure et facile Méthode..

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;
     }
}
 3
Author: Keshav bansal, 2018-04-20 16:31:33

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
    }
}
 3
Author: user2875404, 2018-04-20 16:32:09

Utiliser 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

 3
Author: Rumesh Eranga, 2018-04-20 16:34:23

Une autre solution, mentionnée sans exemple (cela fonctionne en fait dans le code prod).

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é avec no-stack-trace:

private static class BreakLoopException extends Exception {
    @Override
    public StackTraceElement[] getStackTrace() {
        return new StackTraceElement[0];
    }
}
 3
Author: ursa, 2018-04-20 17:47:54
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;
    }
}
 2
Author: Panzercrisis, 2013-09-11 22:14:59

Je voulais répondre à à cette question mais j'ai été marqué comme un doublon, ce qui m'empêche également de poster. Donc, le poster ici à la place !

Si c'est une nouvelle implémentation, vous pouvez essayer de réécrire la logique comme si-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 a s'est produit et vérifiez 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 à partir d'un langage de programmation en java et je veux juste faire fonctionner la chose, vous pouvez essayer d'utiliser labels

 2
Author: Ravindra HV, 2017-05-23 12:02:50

Démo pour break, continue, label.

Donc les mots clés java break et continue ont la valeur par défaut, c'est la "Boucle la plus proche", Toady quelques années après l'utilisation de Java, je viens de l'avoir !

Il semble utilisé 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);
                }
            }
        }
    }

}
 2
Author: Bill, 2018-01-12 10:43:31

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

Ici, dans ce cas, les boucles imbriquées complètes doivent être exit si la condition est True . Mais si nous utilisons exitloops uniquement vers le haut loop

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

Alors la boucle intérieure continuera, car il n'y a pas d'indicateur supplémentaire qui informe cette boucle intérieure de quitter.

Exemple : si i = 3 et j=2, puis la condition est false. Mais dans l'itération suivante de la boucle interne {[10] } alors la condition (i*j) devient 9 qui est true mais la boucle interne sera continuer jusqu'à ce que j devienne 5.

Donc, il doit également utiliser 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);
    }
}
 2
Author: Vikrant Kashyap, 2018-04-20 16:28:31

Comme la suggestion d'INFORMATIONS @1800, utilisez la condition qui casse la boucle interne comme 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;
        }
    }
}
 2
Author: mtyson, 2018-04-20 16:33:07

Vous pouvez faire ce qui suit:

  1. Définir une variable locale à false

  2. Définissez cette variable true dans la première boucle, quand vous voulez briser

  3. , Alors vous pouvez vérifier dans la boucle externe, que si la condition est définie, alors rupture de la boucle externe ainsi.

    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
        }
    }
    
 1
Author: Siddharth Choudhary, 2018-04-20 16:26:48

Dans certains cas, Nous pouvons utiliser la boucle while efficacement 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;
}
 1
Author: Dharmik Patel, 2018-04-20 16:28:15

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

Comme ceci :

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;
}
 1
Author: tejas, 2018-04-20 16:31:18
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 lorsque vous avez terminé le traitement. Ensuite, la boucle interne ne continue que lorsque la condition n'a pas été remplie. De toute façon, la boucle extérieure continuera à chuggin'.

 0
Author: astryk, 2018-04-20 16:33:48

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

public static void main(String ...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");
}
 0
Author: Harsh Vardhan, 2018-08-04 11:59:44

Vous utilisez simplement l'étiquette pour casser les boucles intérieures

public class Test {
public static void main(String[] 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");
}
}
 -1
Author: Mahesh P, 2012-10-25 08:39:43

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 a été quittée:

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   
     } 
}
 -1
Author: Edd, 2013-05-07 18:57:20