Comment sortir de boucles imbriquées en Java?

j'ai une construction de boucle imbriquée comme celle-ci:

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 parce que la plupart ont utilisé gotos.

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

mise à jour: Je ne veux pas rediriger les boucles, en cassant je suis fini avec l'exécution du bloc de boucle.

1571
demandé sur Steve Chambers 2009-05-20 13:07:43

30 réponses

comme les autres answerers, je préférerais certainement mettre la boucle intérieure 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");
    }
}

Cette affiche:

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
répondu Jon Skeet 2018-04-20 17:11:39

techniquement, la bonne réponse est d'étiqueter la boucle extérieure. Dans la pratique, si vous voulez sortir à n'importe quel point à l'intérieur d'une boucle interne alors vous feriez mieux d'extériorisation le code dans une méthode (une méthode statique si besoin est) et ensuite l'appeler.

qui paierait 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 de 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
répondu 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
répondu Joey 2009-05-20 09:12:12

Je n'utilise jamais d'étiquettes. Il semble comme une mauvaise pratique. 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
répondu Elle Mundy 2014-08-04 17:18:10

vous pouvez utiliser les étiquettes:

label1: 
for (int i = 0;;) {
    for (int g = 0;;) {
      break label1;
    }
}
81
répondu 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
répondu 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 sortir / revenir de la boucle intérieure:

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

si vous n'aimez pas break s et goto s, vous pouvez utiliser un" traditionnel "pour boucle à la place du for-in, avec une condition supplémentaire d'abandon:

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
répondu 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 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
répondu Swifty McSwifterton 2016-11-10 08:54:50

je préfère ajouter une" sortie " 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
répondu 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
répondu Igor Rybak 2018-04-20 17:46:58

vous pouvez casser de toutes les boucles sans utiliser aucune étiquette: et des drapeaux.

c'est juste une solution délicate.

Ici condition1 est la condition qui est utilisé pour casser de la boucle K et J. Et condition2 est la condition qui est utilisé pour casser de 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
répondu Hitendra Hckr 2015-04-25 22:44:38

plutôt pendant longtemps je pensais à partager ce type de réponse pour ce type de question.

habituellement, de tels cas entrent dans la portée d'une logique plus significative, disons une recherche ou une manipulation sur certains des 'pour'itérés' -objets en question, donc j'utilise habituellement 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;
}

Grands inconvénients:

  • environ deux fois plus de lignes
  • plus de consommation de cycles de calcul, ce qui signifie qu'il est plus lent d'un point de vue algorithmique
  • plus de travaux de Dactylographie

Les pros:

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

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

Essentiellement d'une question à l'auteur de cette question: que pensez-vous de cette approche?

4
répondu Oleksii Kyslytsyn 2016-01-28 19:14:59

si elle est à l'intérieur d'une fonction, pourquoi ne pas la retourner:

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

meilleure méthode et facile..

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
répondu 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 facile que vous pourriez 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
répondu 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;
}

Consultez cet article

3
répondu Rumesh Eranga 2018-04-20 16:34:23

une autre solution, mentionnée sans exemple (elle 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 doit ê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
répondu 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
répondu Panzercrisis 2013-09-11 22:14:59

je voulais répondre cette question mais a été marqué comme un double qui m'empêche de poster aussi. Alors affichez-le 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 mettre un drapeau quand cette condition spéciale a produit et vérifier que le drapeau dans chaque votre boucle conditions.

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 transférez simplement la logique d'un langage de programmation À java et que vous voulez juste faire fonctionner la chose, vous pouvez essayer d'utiliser étiquettes

2
répondu Ravindra HV 2017-05-23 12:02:50

démo pour break , continue , label .

donc les mots clés java break et continue ont une valeur par défaut, c'est la" boucle la plus proche", déjà quelques années après L'utilisation de Java, je viens de l'obtenir !

ça 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);
                }
            }
        }
    }

}
2
répondu Bill 2018-01-12 10:43:31

for (int j = 0; j < 5; j++) //inner loop doit ê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 seulement vers le haut loop

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

alors la boucle intérieure continuera, parce qu'il n'y a pas de drapeau supplémentaire qui avertit cette boucle intérieure de sortir.

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

ainsi, il doit utiliser exitloops aux boucles intérieures aussi.

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
répondu Vikrant Kashyap 2018-04-20 16:28:31

comme @1800 suggestion D'INFORMATION, 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
répondu mtyson 2018-04-20 16:33:07

vous pouvez faire ce qui suit:

  1. fixe une variable locale à false

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

  3. ensuite, vous pouvez vérifier dans la boucle extérieure, que si la condition est réglée puis briser de la boucle extérieure aussi bien.

    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
répondu Siddharth Choudhary 2018-04-20 16:26:48

pour certains cas, nous pouvons utiliser efficacement la boucle while 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
répondu Dharmik Patel 2018-04-20 16:28:15

même en créant un drapeau pour boucle extérieure et en vérifiant qu'après chaque exécution de boucle intérieure 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
répondu 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
    }
}

utiliser la condition comme un drapeau pour quand vous avez terminé le traitement. Ensuite, la boucle interne seulement continue tant que la condition n'est pas remplie. Quoi qu'il en soit, la boucle extérieure va continuer.

0
répondu astryk 2018-04-20 16:33:48

Java n'a pas de fonctionnalité goto comme il en existe en C++. Mais tout de même, goto est un mot-clé réservé en Java. Ils pourraient la mettre en œuvre à l'avenir. Pour votre question, la réponse est qu'il y a quelque chose appelé étiquette en Java à laquelle vous pouvez appliquer une déclaration continue et break . Trouver 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
répondu Harsh Vardhan 2018-08-04 11:59:44

il suffit d'utiliser l'étiquette pour briser 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
répondu Mahesh P 2012-10-25 08:39:43

vérifiez si la boucle intérieure est sortie avec une instruction if, en cochant la variable de la boucle intérieure. Vous pouvez également créer une autre variable comme un booléen pour vérifier si la boucle interne est terminée.

dans cet exemple, il utilise la variable de la boucle intérieure pour vérifier si elle a été retiré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
répondu Edd 2013-05-07 18:57:20