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.

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

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

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

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

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

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

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

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

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

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

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

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?


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

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

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

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

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

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


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

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

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

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 .


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

2

Próbny

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

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

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

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

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

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.