for - while loop java




Ausbrechen von verschachtelten Schleifen in Java (20)

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

In diesem Beispiel wird die Variable der inneren Schleife verwendet, um zu überprüfen, 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   
     } 
}

Ich habe ein Nested-Loop-Konstrukt 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 jetzt aus beiden Schleifen ausbrechen? Ich habe ähnliche Fragen untersucht, aber keine betrifft Java. Ich konnte diese Lösungen nicht anwenden, weil die meisten gotos verwendet wurden.

Ich möchte die innere Schleife nicht in eine andere Methode bringen.

Update: Ich möchte die Schleifen nicht mehr ausführen, beim Brechen bin ich mit der Ausführung des Schleifenblocks fertig.


(BEARBEITEN: Wie andere Beantworter würde ich definitiv die innere Schleife in eine andere Methode legen. 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. Beispielsweise:

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

Demo für break , continue , label .

Also Java Keywords, die break und continue haben Standardwerte, es ist die "Nearest Loop", Toady ein paar Jahre nach der Verwendung von Java, ich habe es gerade!

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

}

Eher ungewöhnliche Vorgehensweise, aber in Bezug auf die Codelänge ( nicht Leistung ) ist dies die einfachste Sache, die 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
    }
}

Ich benutze nie Etiketten. Es scheint eine schlechte Übung 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;
        }
    }
}

Ich bevorzuge es, den Loop-Tests einen expliziten "Exit" hinzuzufügen. Es macht jedem zufälligen Leser klar, dass die Schleife möglicherweise vorzeitig beendet wird.

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

Ich habe lange überlegt, diese Art von Antwort für diese Art von Frage zu teilen.

Normalerweise sind solche Fälle im Rahmen einer aussagekräftigeren Logik, sagen wir einige, die nach einigen der iterierten For-Objekten suchen oder diese manipulieren, also 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, was bedeutet, dass es aus algorithmischer Sicht langsamer ist
  • mehr Tipparbeit

Die Profis:

  • das höhere Verhältnis zur Trennung von Bedenken wegen der funktionellen 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 leichter zu verstehen
  • subjektiv höheres Verhältnis der Lesbarkeit

Es geht also nur darum, den Fall über einen anderen Ansatz zu behandeln.

Grundsätzlich eine Frage an den Autor dieser Frage: Was halten Sie von diesem Ansatz?


Ich musste eine ähnliche Sache machen, aber ich entschied mich dafür, die erweiterte for-Schleife nicht zu benutzen.

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

In einigen Fällen können wir die while Schleife hier 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;
  }

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

Sie können aus allen Loops brechen, ohne ein Label zu verwenden: und Flags.

Es ist nur eine knifflige Lösung.

Hier ist Bedingung1 die Bedingung, die verwendet wird, um aus der Schleife K und J zu brechen. Und Bedingung2 ist die Bedingung, die verwendet wird, um von der Schleife K, J und I abzubrechen.

Beispielsweise:

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

Sie können eine Sache tun

1.) setze eine lokale Variable auf false

2.) setze diese Variable in der ersten Schleife auf wahr, wenn du ausbrechen willst

3.) dann kannst du in der äußeren Schleife einchecken, ob die Bedingung gesetzt ist, dann auch von der äußeren Schleife abbrechen.

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

Nun, es schien mir eine einfache Art, das so zu sagen.


Sie können einen benannten Block um die Loops verwenden:

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

Sie verwenden nur Etiketten zum Aufbrechen innerer Schleifen

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

Technisch ist die korrekte Antwort, die äußere Schleife zu beschriften. In der Praxis, wenn Sie an einem beliebigen Punkt innerhalb einer inneren Schleife beenden möchten, wäre es besser, den Code in eine Methode (eine statische Methode, falls erforderlich) zu externalisieren und sie dann aufzurufen.

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

Der Code würde so etwas werden:

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

Übereinstimmendes Beispiel für die akzeptierte Antwort:

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


Wenn es in einer Funktion ist, warum gibst du es nicht einfach zurück:

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

Wie @ 1800 INFORMATION Vorschlag, verwenden Sie die Bedingung, die die innere Schleife als Bedingung auf der äußeren Schleife bricht:

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

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

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

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

Dann wird die innere Schleife fortgesetzt, da kein zusätzliches Flag vorhanden ist, das diese innere Schleife zum Beenden auffordert.

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

Also, es muss auch exitloops zu den inneren Loops 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);
        }
    }

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




loops