it-swarm.com.de

Wie kann ich verschachtelte Schleifen in Java lösen?

Ich habe ein verschachteltes Schleifenkonstrukt wie folgt:

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

Wie kann ich nun aus beiden Schleifen ausbrechen? Ich habe mir ähnliche Fragen angeschaut, aber keine betrifft Java. Ich konnte diese Lösungen nicht anwenden, da die meisten gotischen Methoden verwendet wurden.

Ich möchte die innere Schleife nicht auf eine andere Weise einsetzen.

Ich möchte die Schleifen nicht wiederholen. Beim Brechen bin ich mit der Ausführung des Schleifenblocks fertig.

1635
boutta

Wie andere Antworter würde ich definitiv lieber die Loops auf eine andere Art und Weise verwenden, an dem Punkt, an dem Sie einfach zurückkehren können, um die Iteration vollständig zu beenden. Diese Antwort zeigt nur, wie die Anforderungen in der Frage erfüllt werden können.

Sie können break mit einem Label für die äußere Schleife verwenden. Zum Beispiel:

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");
    }
}

Dies druckt:

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
2201
Jon Skeet

Technisch ist die richtige Antwort, die äußere Schleife zu kennzeichnen. Wenn Sie in der Praxis an einer beliebigen Stelle innerhalb einer inneren Schleife abbrechen möchten, sollten Sie den Code besser in eine Methode (eine statische Methode, wenn nötig) externalisieren und dann aufrufen.

Das würde sich für die Lesbarkeit rechnen. 

Der Code würde in etwa so aussehen: 

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

Das Beispiel für die akzeptierte Antwort abgleichen:

 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);
            }
        }
    }
}
379
Zo72

Sie können einen benannten Block für die Schleifen verwenden:

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

Ich benutze niemals Etiketten. Es scheint eine schlechte Praxis zu sein. Folgendes würde ich tun:

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;
        }
    }
}
120
Elle Mundy

Sie können Etiketten verwenden:

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

Verwenden Sie eine Funktion:

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;
      }
    }
  }
}
34
Fortega

Sie können eine temporäre Variable verwenden:

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
         }
    }
}

Abhängig von Ihrer Funktion können Sie auch die innere Schleife verlassen oder zurückkehren:

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

Wenn Sie breaks und gotos nicht mögen, können Sie anstelle des For-In eine "traditionelle" for-Schleife mit einer zusätzlichen Abbruchbedingung verwenden:

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;
        }
    }
}
11
zord

Ich musste etwas Ähnliches tun, entschied mich jedoch dafür, die erweiterte for-Schleife nicht zu verwenden.

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;
        }
    }
}
10

Ich bevorzuge es, den Schleifentests ein explizites "Exit" hinzuzufügen. Es macht jedem zufälligen Leser klar, dass die Schleife vorzeitig beendet werden kann.

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

Java 8 Stream Lösung:

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**/);
6
Igor Rybak

Sie können aus allen Schleifen ausbrechen, ohne ein Label oder Flag zu verwenden.

Es ist nur eine knifflige Lösung.

Hier ist Bedingung1 die Bedingung, die verwendet wird, um aus den Schleifen K und J zu springen .. und Bedingung2 ist die Bedingung, die verwendet wird, um aus der Schleife K, J und I zu brechen.

Zum Beispiel:

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");
    }
}
5
Hitendra Hckr

Normalerweise kommt in solchen Fällen eine sinnvollere Logik in Betracht. Nehmen wir an, einige der iterierten 'for'-Objekte werden gesucht oder manipuliert, daher verwende ich normalerweise den funktionalen Ansatz:

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;
}

Haupt Nachteile:

  • ungefähr zweimal mehr Zeilen
  • mehr Verbrauch von Rechenzyklen, dh aus algorithmischer Sicht langsamer
  • mehr Schreibarbeit

Die Profis:

  • das höhere Verhältnis zur Trennung der Bedenken aufgrund der funktionalen Granularität
  • das höhere Verhältnis von Wiederverwendbarkeit und Kontrolle der Such-/Manipulationslogik ohne
  • die Methoden sind nicht lang, daher sind sie kompakter und verständlicher
  • subjektiv höheres Leseverhältnis

Es handelt sich also lediglich um eine andere Vorgehensweise.

Im Grunde eine Frage an den Autor dieser Frage: Was halten Sie von diesem Ansatz?

5

Beste und einfache Methode ..

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
Keshav bansal

Wenn es in einer Funktion ist, warum geben Sie es nicht einfach zurück: 

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

Eher ungewöhnlicher Ansatz, aber in Bezug auf die Codelänge ( nicht die Leistung ) ist dies das Einfachste, was Sie tun können:

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
user2875404

Verwenden Sie Etiketten.

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

Siehe diesen Artikel

3
Rumesh Eranga

Eine andere Lösung, die ohne Beispiel erwähnt wurde (sie funktioniert tatsächlich im Prod-Code).

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.
}

Natürlich sollte BreakLoopException intern, privat und mit No-Stack-Trace beschleunigt sein:

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

Demo für break, continue und label:

Die Java-Schlüsselwörter break und continue haben einen Standardwert. Es ist die "nächste Schleife", und heute, nach ein paar Jahren der Verwendung von Java, habe ich es einfach verstanden!

Es scheint selten, aber nützlich zu sein.

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
Bill

for (int j = 0; j < 5; j++) //inner loop sollte durch for (int j = 0; j < 5 && !exitloops; j++) ersetzt werden.

In diesem Fall sollten vollständige verschachtelte Schleifen beendet werden, wenn die Bedingung True lautet. Aber wenn wir exitloops nur zum oberen loop verwenden

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

Dann wird die innere Schleife fortgesetzt, da es kein zusätzliches Flag gibt, das diese innere Schleife zum Verlassen benachrichtigt.

Beispiel: Wenn i = 3 Und j=2, Lautet die Bedingung false. Aber in der nächsten Iteration der inneren Schleife j=3 Wird die Bedingung (i*j) Zu 9, Die true ist, aber die innere Schleife wird fortgesetzt, bis j wird 5.

Also muss es exitloops auch für die inneren Schleifen verwenden.

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
Vikrant Kashyap

Verwenden Sie wie beim Vorschlag von @ 1800 INFORMATION die Bedingung, die die innere Schleife als Bedingung der äußeren Schleife unterbricht:

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
mtyson
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
Panzercrisis

Wenn es sich um eine neue Implementierung handelt, können Sie versuchen, die Logik als if-else_if-else-Anweisungen umzuschreiben.

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
    }
}

Andernfalls können Sie versuchen, ein Flag zu setzen, wenn diese spezielle Bedingung aufgetreten ist, und überprüfen, ob dieses Flag in jeder Ihrer Schleifenbedingungen vorhanden ist.

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) { // The things below will not be executed
        continue;
    }

    // Other things may happen here as well, but they will not be executed
    //  once control is returned from the inner cycle.
}

HIER! Eine einfache Pause funktioniert zwar nicht, kann aber mit continue ausgeführt werden.

Wenn Sie die Logik einfach von einer Programmiersprache nach Java portieren und die Sache zum Laufen bringen wollen, können Sie versuchen, labels zu verwenden.

2
Ravindra HV

Labeled break concept wird verwendet, um verschachtelte Schleifen in Java aufzubrechen. Durch die Verwendung von Labeled break können Sie die Verschachtelung von Schleifen an einer beliebigen Position aufheben. Beispiel 1:

loop1:
 for(int i= 0; i<6; i++){
    for(int j=0; j<5; j++){
          if(i==3)
            break loop1;
        }
    }

angenommen, es gibt 3 Schleifen und Sie möchten die Schleife 3 beenden: Beispiel 2:

loop3: 
for(int i= 0; i<6; i++){
loop2:
  for(int k= 0; k<6; k++){
loop1:
    for(int j=0; j<5; j++){
          if(i==3)
            break loop3;
        }
    }
}
1
Bishal Jaiswal

Demo

public static void main(String[] args) {
    outer:
    while (true) {
        while (true) {
            break outer;
        }
    }
}
1
shellhub

Sie können Folgendes tun:

  1. setze eine lokale Variable auf false

  2. setzen Sie diese Variable true in der ersten Schleife, wenn Sie brechen möchten

  3. dann kannst du in der äußeren Schleife prüfen, ob die Bedingung dann auch von der äußeren Schleife abgebrochen wird.

    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
        }
    }
    

In einigen Fällen können wir hier while loop effektiv verwenden.

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
Dharmik Patel

Auch das Erstellen eines Flags für die äußere Schleife und die Überprüfung, dass nach jeder Ausführung der inneren Schleife die Antwort sein kann.

So was:

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
tejas

Überprüfen Sie, ob die innere Schleife mit einer if-Anweisung verlassen wird, indem Sie die Variable der inneren Schleife überprüfen. Sie können auch eine andere Variable erstellen, z. B. einen Booleschen Wert, um zu überprüfen, ob die innere Schleife beendet wird.

In diesem Beispiel wird anhand der Variablen der inneren Schleife überprüft, ob sie beendet wurde:

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   
     } 
}
0
Edd

Verwenden Sie einfach label, um innere Schleifen zu durchbrechen

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");
}
}
0
Mahesh P

Unten sehen Sie ein Beispiel, in dem die Anweisung "break" den Cursor aus der for-Schleife drückt, wenn die Bedingung erfüllt ist.

public class Practice3_FindDuplicateNumber {

    public static void main(String[] args) {
        Integer[] inp = { 2, 3, 4, 3, 3 };
        Integer[] aux_arr = new Integer[inp.length];
        boolean isduplicate = false;
        for (int i = 0; i < aux_arr.length; i++) {

            aux_arr[i] = -1;

        }
        outer: for (int i = 0; i < inp.length; i++) {
            if (aux_arr[inp[i]] == -200) {
                System.out.println("Duplicate Found at index: " + i + " Carrying value: " + inp[i]);
                isduplicate = true;
                break outer;
            } else {
                aux_arr[inp[i]] = -200;
            }
        }

        for (Integer integer : aux_arr) {
            System.out.println(integer);
        }

        if (isduplicate == false) {
            System.out.println("No Duplicates!!!!!");
        } else {
            System.out.println("Duplicates!!!!!");
        }
    }

}
0
Deb

Java hat keine Goto-Funktion wie in C++. Dennoch ist goto ein in Java reserviertes Schlüsselwort. Sie könnten es in Zukunft umsetzen. Für Ihre Frage lautet die Antwort, dass es in Java ein so genanntes Label gibt, auf das Sie eine continue- und break-Anweisung anwenden können. Den Code finden Sie unten:

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
Harsh Vardhan
boolean condition = false;
for (Type type : types) {
    for (int i = 0; i < otherTypes.size && !condition; i ++) {
        condition = true; // If your condition is satisfied
    }
}

Verwenden Sie condition als Flag, wenn Sie mit der Verarbeitung fertig sind. Dann läuft die innere Schleife nur weiter, wenn die Bedingung nicht erfüllt ist. In jedem Fall bleibt die äußere Schleife auf "chuggin".

0
astryk