Jak wyjść z zagnieżdżonych pętli w Javie?

1818

Mam zagnieżdżoną konstrukcję pętli:

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

Jak mogę teraz wyjść z obu pętli? Patrzyłem na podobne pytania, ale żadne nie dotyczy konkretnie Javy. Nie mogłem zastosować tych rozwiązań, ponieważ najczęściej używane gotos.

Nie chcę umieszczać wewnętrznej pętli w innej metodzie.

Nie chcę ponownie uruchamiać pętli. Po zerwaniu kończę wykonywanie bloku pętli.

boutta
źródło

Odpowiedzi:

2427

Podobnie jak inne Główni odpowiadający, zdecydowanie wolą zastosować pętle w innej metodzie, w którym to momencie możesz po prostu wrócić, aby całkowicie przestać iterować. Ta odpowiedź pokazuje, w jaki sposób można spełnić wymagania zawarte w pytaniu.

Możesz użyć breakz etykietą dla zewnętrznej pętli. Na przykład:

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

To drukuje:

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
Jon Skeet
źródło
286
To ma przeskoczyć bezpośrednio po pętli. Spróbuj! Tak, etykieta znajduje się przed pętlą, ale dzieje się tak dlatego, że oznacza ona etykietę pętli, a nie miejsce, do którego chcesz wyjść. (Możesz też kontynuować z etykietą.)
Jon Skeet,
2
Perl zezwala również na własny system etykiet. Myślę, że robi to w wielu językach - nie dziwi mnie, że jest w Javie.
Evan Carroll,
9
@Evan - to twierdzenie jest oczywiście prawdziwe - w językach, które obiecują, że to prawda. Ale Java nie składa takiej obietnicy. Jeśli język jest w konflikcie z twoimi założeniami, możliwe, że to wina twoich założeń. W tym przypadku myślę, że nadal masz częściowo rację - zasada najmniejszego zaskoczenia WRT wielu, którzy nigdy nie słyszeli (lub zapomnieli) o tej formie break. Nawet wtedy wyjątki są kolejnym bardziej znanym wyjątkiem (przepraszam). Ale nadal byłbym niezadowolony z tego, gdyby nie było to oczywiste (małe pętle, komentarz ostrzegawczy, jeśli etykieta / przerwa wciąż nie są wystarczająco widoczne).
Steve314,
6
@MuhammadBabar: outerloopto etykieta. Nie wiem dokładnie, jakiego kodu próbowałeś, ale kod w mojej odpowiedzi kompiluje się i działa dobrze.
Jon Skeet
4
@NisargPatil Tylko dlatego, że jest w sonarLint, nie powoduje, że kod pachnie. Oznacza to po prostu, że był programista, który dodał to do sonarLint z osobistym swędzeniem do zera i jest pełen takich zasad, które mają sens tylko w przypadku nadużycia lub dlatego, że jakiś programista ma osobistą krucjatę przeciwko nim. Oznaczone przerwy i kontynuacje to bardzo elegancki sposób na opisanie tego, co chcesz zrobić.
john16384
402

Technicznie poprawną odpowiedzią jest oznaczenie zewnętrznej pętli. W praktyce, jeśli chcesz wyjść z dowolnego miejsca w wewnętrznej pętli, lepiej byłoby przekazać kod na zewnątrz (metoda statyczna, jeśli to konieczne), a następnie wywołać go.

Opłaci się to za czytelność.

Kod stałby się mniej więcej taki:

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

Dopasowując przykład do zaakceptowanej odpowiedzi:

 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);
            }
        }
    }
}
Zo72
źródło
30
Czasami używasz kilku lokalnych zmiennych, które znajdują się poza wewnętrzną pętlą, przekazywanie ich wszystkich może być niezręczne.
Haoest,
1
Więc jak to rozwiązanie ma wydrukować „Gotowe” jak w zaakceptowanej odpowiedzi?
JohnDoe,
1
@JohnDoe wywołujesz go, a następnie drukujesz System.out.println („gotowe”); spróbuj {} wreszcie {} w ramach metody wyszukiwania jest również opcja.
Zo72
2
To chyba lepsza praktyka, ale co się stanie, jeśli chcesz kontynuować zamiast łamać? Etykiety obsługują równie dobrze (lub źle!), Ale nie jestem pewien, jak przekonwertować tę logikę, aby kontynuować.
Rob Grant,
@RobertGrant Jeśli chcesz kontynuować zamiast przerwać, przenieś zewnętrzną pętlę poza loopmetodę i wróć z metody, aby kontynuować.
Muhd
215

Możesz użyć nazwanego bloku wokół pętli:

search: {
    for (Type type : types) {
        for (Type t : types2) {
            if (some condition) {
                // Do something and break...
                break search;
            }
        }
    }
}
Joey
źródło
40
Nie musisz tworzyć nowego bloku, aby użyć etykiety.
Jon Skeet
81
Nie, ale dzięki temu intencja jest o wiele wyraźniejsza. Zobacz pierwszy komentarz do zaakceptowanej odpowiedzi.
Bombe
2
to właściwie nie jest nazwany blok, po etykiecie można napisać dowolne wyrażenie Java, ponieważ bez etykiety, czy name: if(...){...}warunek jest nazwany? :)
La VloZ Merrill 21.04.16
4
Ten konstrukt ma dużą przewagę nad forbezpośrednim oznaczaniem . Możesz dodać kod przed ostatnim, }który zostanie wykonany tylko wtedy, gdy warunek nigdy nie zostanie spełniony.
Florian F
2
Jest to nazwany blok, a nie nazwana pętla. Nie można w ramach tej pętli „kontynuować wyszukiwanie”; co jest całkowicie legalną składnią, jeśli pętla nosi nazwę search. Możesz go złamać, ale nie możesz kontynuować.
Tatarize
132

Nigdy nie używam etykiet. Wydaje się, że jest to zła praktyka. Oto co bym zrobił:

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;
        }
    }
}
Elle Mundy
źródło
4
Jeżeli nie będzie to && !finishedzamiast || !finished? Dlaczego więc breakw ogóle używać, a nie używać również && !finisheddo wewnętrznej pętli?
Gandalf
4
Zwykle mogę breakdowolnie wychodzić z pętli. Jeśli po tym ifbloku jest kod , możesz go wykonać break. Ale masz rację &&. Naprawione.
Elle Mundy
2
fajne rozwiązanie! tak właśnie zrobiłbym to w praktyce, jeśli z jakiegoś powodu nie jest preferowane wprowadzenie dodatkowej funkcji.
benroth,
6
Istnieje potencjalny problem, jeśli po wewnętrznej pętli jest jakaś logika ... która będzie nadal wykonywana, a zewnętrzna pętla zostanie zerwana dopiero, gdy rozpocznie się nowa iteracja ...
Karthik Karuppannan
7
Nie rozumiem, dlaczego należy tak to robić. Osoby pracujące z kodem powinny mieć możliwość korzystania ze wszystkich funkcji języka. Rozumiem, że ważne jest, aby pisać kod, który inni mogą zrozumieć, ale nie ograniczając korzystania z oficjalnych narzędzi udostępnianych przez język i znajdując obejścia dla tej samej funkcjonalności. A może miałeś na myśli coś innego przez „złą praktykę”?
codepleb
107

Możesz użyć etykiet:

label1: 
for (int i = 0;;) {
    for (int g = 0;;) {
      break label1;
    }
}
simon622
źródło
4
Masz ode mnie +1. Proste, do rzeczy, odpowiada na pytanie. Nie można zarzucić, że powtórzyłeś istniejącą odpowiedź, ponieważ odpowiedziałeś w tym samym czasie.
Heimdall,
40

Użyj funkcji:

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;
      }
    }
  }
}
Fortega
źródło
20

Możesz użyć zmiennej tymczasowej:

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

W zależności od funkcji możesz także wyjść / wrócić z pętli wewnętrznej:

for (Type type : types) {
    for (Type t : types2) {
         if (some condition) {
             // Do something and break...
             return;
         }
    }
}
Miguel Ping
źródło
7
Uważam, że ten sposób jest trochę zagracony.
boutta
11
Dodatkowa kontrola stanu za każdym razem przez pętlę? Nie, dziękuję.
ryandenki
15

Jeśli nie lubisz breaks i gotos, możesz użyć „tradycyjnej” pętli for zamiast zamiast for-in, z dodatkowym warunkiem przerwania:

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;
        }
    }
}
zord
źródło
2
Nie nadaje się do zapętlania pętli.
John McClane,
1
@JohnMcClane I spamujesz to na wiele odpowiedzi na pytanie 9+ lat, ponieważ ...?
Quintec
12

Musiałem zrobić coś podobnego, ale postanowiłem nie używać do tego ulepszonej pętli for.

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;
        }
    }
}
Swifty McSwifterton
źródło
Nie jest fajnie iterować wszystkich elementów po spełnieniu warunku. Dodałbym zatem przerwę w przypadku else.
boutta
@boutta Nie jestem pewien, w jaki sposób dochodzisz do tego wniosku. Gdy warunek jest spełniony, obie pętle zostają zakończone.
Swifty McSwifterton
OK, nie dostałem części z manipulacją zmienną 's'. Ale uważam ten rodzaj złego stylu, ponieważ s reprezentuje rozmiar. Następnie wolę odpowiedź od ddyera z wyraźnymi zmiennymi: stackoverflow.com/a/25124317/15108
boutta
@boutta Możesz zmienić swartość na niższą ilub zmienić ina wartość większą lub równą niż s, obie powinny załatwić sprawę. Masz rację co do zmiany s, ponieważ można go użyć w innym miejscu później, ale zmiana inie zaszkodzi, po prostu upewni się, że pierwsza fornie będzie kontynuować pętli.
Zsolti
9

Wolę dodać wyraźne „wyjście” do testów pętli. Dla każdego zwykłego czytelnika jest jasne, że pętla może zakończyć się wcześniej.

boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
     for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
ddyer
źródło
Nie nadaje się do zapętlania pętli.
John McClane,
8

StreamRozwiązanie Java 8 :

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**/);
Igor Rybak
źródło
1
@ Tvde1 i nadal przydatny dla innych użytkowników, więc nowe metody i rozwiązania są zawsze mile widziane
Andrei Suvorkov 16.04.19
Wow, to brzydkie.
DS.
7

Zwykle w takich przypadkach wchodzi w zakres bardziej sensownej logiki, powiedzmy, że niektóre szukają lub manipulują niektórymi iterowanymi obiektami „for”, o których mowa, więc zwykle używam podejścia funkcjonalnego:

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

Główne wady:

  • około dwa razy więcej linii
  • większe zużycie cykli obliczeniowych, co oznacza, że ​​jest wolniejsze z algorytmicznego punktu widzenia
  • więcej pisania na klawiaturze

Profesjonaliści:

  • wyższy stosunek do oddzielenia problemów z powodu ziarnistości funkcjonalnej
  • wyższy stosunek ponownego wykorzystania i kontroli wyszukiwania / manipulowania logiką bez
  • metody nie są długie, dlatego są bardziej zwarte i łatwiejsze do zrozumienia
  • wyższy współczynnik czytelności

Więc po prostu zajmuje się sprawą za pomocą innego podejścia.

Zasadniczo pytanie do autora tego pytania: co sądzisz o tym podejściu?

Oleksii Kyslytsyn
źródło
6

Możesz zerwać ze wszystkich pętli bez użycia etykiet: i flag.

To po prostu trudne rozwiązanie.

Tutaj warunek 1 jest warunkiem, który jest używany do zerwania z pętli K i J. A warunek 2 jest warunkiem, który jest używany do zerwania z pętli K, J i I.

Na przykład:

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");
    }
}
Hitendra Solanki
źródło
2
Jak miałbym tego używać z pętlami dla każdej z nich? ;)
Willi Mentzel
5
To nie działa, jeśli masz bardziej wyrafinowane warunki pętli, takie jak list.size ()> 5. To jest naprawdę tylko hack. Trudno to przeczytać i zła praktyka!
Neuron
Jest podatny na błędy. Wyobraź sobie, że zmienił wewnętrzną pętlę (int k = 0; k < 10; k++)i nie naprawić wszystkie z k = 9celu k = 10. Możesz dostać się w nieskończoną pętlę.
Florian F
5

Koncepcja przerwania z etykietą służy do rozbijania zagnieżdżonych pętli w Javie, przy użyciu przerwania z etykietą można przerwać zagnieżdżanie pętli w dowolnej pozycji. Przykład 1:

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

załóżmy, że istnieją 3 pętle i chcesz zakończyć pętlę 3: Przykład 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;
        }
    }
}
Bishal Jaiswal
źródło
4
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;
    }
}
Panzercrisis
źródło
4

Jeśli jest w jakiejś funkcji, dlaczego po prostu jej nie zwrócisz:

for (Type type : types) {
    for (Type t : types2) {
         if (some condition) {
            return value;
         }
    }
}
Chit Khine
źródło
Wolę ten wzór. Często powodowało to, że pękałem w osobnej funkcji. Mój kod zawsze był lepszy po tym, więc z tego powodu bardzo podoba mi się ta odpowiedź.
Bill K
4

Najlepsza i łatwa metoda ..

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;
     }
}
Keshav Bansal
źródło
4
Te przykłady łamania nie są zbyt pomocne, ponieważ nawet bez etykiety pękłyby w tym samym momencie. Poza tym zawsze miło jest mieć kod, który można wykonać, co nie ma miejsca w przypadku twojego kodu, ponieważ wewnętrzna pętla nigdy nie jest dostępna.
Neuron
Zamierzałem wpisać to samo. Etykiety są w tym przypadku nieco bezużyteczne.
Taslim Oseni
4

Raczej nietypowe podejście, ale pod względem długości kodu ( nie wydajności ) jest to najłatwiejsza rzecz, jaką możesz zrobić:

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
    }
}
użytkownik 2875404
źródło
4

Użyj etykiet.

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

Zobacz ten artykuł

Rumesh Eranga Hapuarachchi
źródło
4

Kolejne rozwiązanie, wspomniane bez przykładu (faktycznie działa w kodzie 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.
}

Oczywiście BreakLoopExceptionpowinny być wewnętrzne, prywatne i przyspieszone bez śledzenia stosu:

private static class BreakLoopException extends Exception {
    @Override
    public StackTraceElement[] getStackTrace() {
        return new StackTraceElement[0];
    }
}
ursa
źródło
1
Zostało to faktycznie wspomniane, w odpowiedzi uzyskując -23 głosów ... stackoverflow.com/a/886980/2516301 .
Wykona
w rzeczy samej. widziałem jednak taki starszy kod - 4-poziomowe zagnieżdżone pętle z kilkoma warunkami zerwania. i był bardziej czytelny z wyjątkami niż z wbudowanym kodem. -23 głosów to głównie ocena emocjonalna, ale tak - należy ostrożnie stosować to podejście.
ursa,
1
Byłby jeszcze bardziej czytelny, gdyby został podzielony na osobne wywołanie funkcji ze zwrotem środkowym. Często ulepszany przez mały refaktor, więc ma sens jako samodzielna (często wielokrotnego użytku) funkcja.
Bill K
2

for (int j = 0; j < 5; j++) //inner loopnależy zastąpić for (int j = 0; j < 5 && !exitloops; j++).

Tutaj, w tym przypadku, pełne zagnieżdżone pętle powinny zostać zakończone, jeśli warunek jest spełniony True. Ale jeśli używamy exitloopstylko do cholewkiloop

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

Następnie wewnętrzna pętla będzie kontynuowana, ponieważ nie ma dodatkowej flagi, która powiadomiłaby tę wewnętrzną pętlę o wyjściu.

Przykład: jeśli i = 3i j=2wtedy warunkiem jest false. Ale w następnej iteracji wewnętrznej pętli j=3 warunek (i*j)staje się tym, 9co jest, trueale wewnętrzna pętla będzie kontynuowana, aż jstanie się 5.

Musi więc używać również exitloopsdo wewnętrznych pętli.

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);
    }
}
Vikrant Kashyap
źródło
2

Podobnie jak sugestia @ 1800 INFORMACJE, użyj warunku, który przerywa pętlę wewnętrzną, jako warunku w pętli zewnętrznej:

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;
        }
    }
}
mtyson
źródło
2

Jeśli jest to nowa implementacja, możesz spróbować przepisać logikę jako instrukcje 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
    }
}

W przeciwnym razie możesz spróbować ustawić flagę po wystąpieniu tego specjalnego warunku i sprawdzić tę flagę w każdym z warunków pętli.

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

TUTAJ! Tak więc, chociaż prosta przerwa nie będzie działać, można ją wykorzystać do pracy continue.

Jeśli po prostu przenosisz logikę z jednego języka programowania na Javę i po prostu chcesz, aby coś działało, możesz spróbować użyć etykiet .

Ravindra HV
źródło
2

Demo break, continueoraz label:

Słowa kluczowe Java breaki continuemają wartość domyślną. To „najbliższa pętla”, a dziś, po kilku latach używania Javy, właśnie ją dostałem!

Wydaje się, że jest używany rzadko, ale jest użyteczny.

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);
                }
            }
        }
    }
}
Rachunek
źródło
2

Próbny

public static void main(String[] args) {
    outer:
    while (true) {
        while (true) {
            break outer;
        }
    }
}
skorupiak
źródło
1

Możesz wykonać następujące czynności:

  1. ustaw zmienną lokalną na false

  2. ustaw tę zmienną truew pierwszej pętli, gdy chcesz przerwać

  3. następnie możesz sprawdzić w zewnętrznej pętli, czy to, czy warunek jest ustawiony, następnie zerwać z zewnętrznej pętli.

    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
        }
    }
Siddharth Choudhary
źródło
1

W niektórych przypadkach możemy whileefektywnie wykorzystać pętlę tutaj.

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;
}
Dharmik Patel
źródło
1

Java nie ma funkcji goto jak w C ++. Ale nadal gotojest zastrzeżonym słowem kluczowym w Javie. Mogą to wdrożyć w przyszłości. W przypadku twojego pytania odpowiedź jest taka, że ​​w Javie istnieje coś takiego jak etykieta, do którego można zastosować instrukcję continuei break. Znajdź kod poniżej:

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");
}
Surowy Vardhan
źródło
1

Nawet utworzenie flagi dla zewnętrznej pętli i sprawdzenie, że po każdym wykonaniu wewnętrznej pętli może być odpowiedzią.

Lubię to:

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;
}
voidMainReturn
źródło
1
boolean condition = false;
for (Type type : types) {
    for (int i = 0; i < otherTypes.size && !condition; i ++) {
        condition = true; // If your condition is satisfied
    }
}

Użyj conditionjako flagi po zakończeniu przetwarzania. Następnie pętla wewnętrzna jest kontynuowana tylko wtedy, gdy warunek nie jest spełniony. Tak czy inaczej, zewnętrzna pętla będzie się nadal ładować.

astryk
źródło