Làm cách nào để thoát ra khỏi các vòng lặp lồng nhau trong Java?


1818

Tôi đã có một cấu trúc vòng lặp lồng nhau như thế này:

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

Bây giờ làm thế nào tôi có thể thoát ra khỏi cả hai vòng? Tôi đã xem xét các câu hỏi tương tự, nhưng không có gì liên quan đến Java cụ thể. Tôi không thể áp dụng các giải pháp này bởi vì hầu hết các gotos được sử dụng.

Tôi không muốn đặt vòng lặp bên trong theo một phương pháp khác.

Tôi không muốn chạy lại các vòng lặp. Khi phá vỡ tôi đã hoàn thành việc thực hiện khối vòng lặp.

Câu trả lời:


2427

Giống như những người trả lời khác, tôi chắc chắn thích đặt các vòng lặp theo một phương pháp khác, tại thời điểm đó bạn có thể quay lại để dừng lặp lại hoàn toàn. Câu trả lời này chỉ cho thấy làm thế nào các yêu cầu trong câu hỏi có thể được đáp ứng.

Bạn có thể sử dụng breakvới một nhãn cho vòng lặp bên ngoài. Ví dụ:

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

Bản in này:

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
Điều này không nhảy đến trực tiếp sau vòng lặp. Thử nó! Đúng, nhãn xuất hiện trước vòng lặp, nhưng đó là vì nó dán nhãn cho vòng lặp, thay vì nơi bạn muốn thoát. (Bạn cũng có thể tiếp tục với một nhãn.)
Jon Skeet

2
Perl cũng cho phép hệ thống nhãn riêng của mình. Tôi nghĩ rằng rất nhiều ngôn ngữ làm - nó hầu như không làm tôi ngạc nhiên rằng nó có trong Java.
Evan Carroll

9
@Evan - tuyên bố đó rõ ràng là đúng - trong các ngôn ngữ hứa rằng đó là sự thật. Nhưng Java không thực hiện lời hứa đó. Nếu một ngôn ngữ mâu thuẫn với các giả định của bạn, có thể đó là các giả định của bạn có lỗi. Trong trường hợp này, tôi nghĩ bạn vẫn đúng một phần - nguyên tắc ít gây ngạc nhiên nhất cho WRT mà nhiều người chưa bao giờ nghe đến (hoặc quên về) hình thức đó break. Thậm chí sau đó, các ngoại lệ là một ngoại lệ được biết đến nhiều hơn (xin lỗi). Nhưng tôi vẫn không hài lòng về điều này nếu nó không rõ ràng (các vòng lặp nhỏ, nhận xét cảnh báo nếu nhãn / phá vỡ vẫn không hiển thị đủ).
Steve314

6
@MuhammadBabar: outerlooplà nhãn. Tôi không biết chính xác mã nào bạn đã thử, nhưng mã trong câu trả lời của tôi biên dịch và chạy tốt.
Jon Skeet

4
@NisargPatil Chỉ vì nó ở trong sonarLint không làm cho nó có mùi mã. Điều đó chỉ có nghĩa là có một nhà phát triển đã thêm nó vào sonarLint với một vết ngứa cá nhân để gãi, và nó có đầy đủ các loại quy tắc chỉ có ý nghĩa khi bị lạm dụng hoặc bởi vì một số nhà phát triển có một sự ghét bỏ cá nhân đối với họ. Phá vỡ nhãn và tiếp tục là một cách rất thanh lịch để mô tả những gì bạn muốn làm.
john16384

402

Về mặt kỹ thuật, câu trả lời đúng là dán nhãn cho vòng lặp bên ngoài. Trong thực tế nếu bạn muốn thoát tại bất kỳ điểm nào trong vòng lặp bên trong thì tốt hơn hết bạn nên mã hóa bên ngoài vào một phương thức (một phương thức tĩnh nếu cần) và sau đó gọi nó.

Điều đó sẽ trả hết cho khả năng đọc.

Mã sẽ trở thành một cái gì đó như thế:

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

Phù hợp với ví dụ cho câu trả lời được chấp nhận:

 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
Đôi khi bạn sử dụng một số biến cục bộ nằm ngoài vòng lặp bên trong, chuyển tất cả chúng vào có thể cảm thấy lộn xộn.
Haoest

1
Vậy làm thế nào là giải pháp này được cho là in "Xong" như trong câu trả lời được chấp nhận?
JohnDoe

1
@JohnDoe bạn gọi nó và sau đó bạn in System.out.println ("xong"); thử {} cuối cùng {} trong phương thức tìm kiếm cũng là một tùy chọn.
Zo72

2
Đây là cách thực hành tốt hơn tôi đoán, nhưng điều gì xảy ra nếu bạn muốn tiếp tục thay vì phá vỡ? Các nhãn hỗ trợ tốt như nhau (hoặc rất tệ!) Nhưng tôi không chắc chắn làm thế nào để chuyển đổi logic này để tiếp tục.
Rob Grant

@RobertGrant Nếu bạn muốn tiếp tục thay vì ngắt, hãy di chuyển vòng ngoài ra ngoài loopphương thức và quay lại từ phương thức để tiếp tục.
Muhd

215

Bạn có thể sử dụng một khối được đặt tên xung quanh các vòng lặp:

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

40
Bạn không cần tạo một khối mới để sử dụng nhãn.
Jon Skeet

81
Không, nhưng nó làm cho ý định rõ ràng hơn rất nhiều. Xem bình luận đầu tiên về câu trả lời được chấp nhận.
Bombe

2
Nó không thực sự là một khối được đặt tên, sau nhãn bạn có thể viết bất kỳ biểu thức Java nào mà không có nhãn, có name: if(...){...}tạo điều kiện được đặt tên không? :)
La VloZ Merrill

4
Cấu trúc này có một lợi thế lớn so với việc dán nhãn fortrực tiếp. Bạn có thể thêm mã trước mã cuối cùng }sẽ được thực thi chỉ khi điều kiện không bao giờ được đáp ứng.
Florian F

2
Nó là một khối được đặt tên và không phải là một vòng lặp được đặt tên. Bạn không thể trong vòng lặp đó "tiếp tục tìm kiếm;" đó hoàn toàn là một cú pháp hợp pháp nếu vòng lặp được đặt tên là tìm kiếm. Bạn có thể phá vỡ nó, nhưng bạn không thể tiếp tục nó.
Tatarize

132

Tôi không bao giờ sử dụng nhãn. Có vẻ như một thực hành xấu để có được vào. Đây là những gì tôi sẽ làm:

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
Không nên && !finishedthay thế || !finished? Và tại sao sau đó sử dụng breaktất cả và không sử dụng && !finishedcho vòng lặp bên trong quá?
Gandalf

4
Tôi sử dụng breakđể có thể tự ý thoát khỏi vòng lặp. Nếu có mã sau ifkhối đó , bạn có thể breaktrước khi nó thực thi. Nhưng bạn nói đúng &&. Đã sửa nó.
Elle Mundy

2
giải pháp tốt đẹp! đó chính xác là cách tôi thực hiện nó trong thực tế nếu đưa nó vào một chức năng bổ sung không thích hợp hơn vì một số lý do.
benroth

6
Có một vấn đề tiềm ẩn nếu có một số logic sau vòng lặp bên trong ... sẽ tiếp tục được thực thi và vòng lặp bên ngoài chỉ bị phá vỡ khi phép lặp mới bắt đầu ...
Karthik Karuppannan

7
Tôi không hiểu tại sao người ta nên làm như vậy. Những người làm việc với mã phải có thể sử dụng tất cả các tính năng của ngôn ngữ. Tôi hiểu rằng việc viết mã mà người khác có thể hiểu là rất quan trọng, nhưng không phải bằng cách hạn chế sử dụng các công cụ chính thức được cung cấp bởi một ngôn ngữ và tìm cách giải quyết cho cùng chức năng. Hay bạn có ý gì khác bởi "thực hành xấu"?
codepleb

107

Bạn có thể sử dụng nhãn:

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

4
Có +1 từ tôi. Đơn giản, đến mức, trả lời câu hỏi. Không thể bị buộc tội lặp lại câu trả lời hiện có vì bạn đã trả lời cùng một lúc.
Heimdall

40

Sử dụng một chức năng:

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

Bạn có thể sử dụng một biến tạm thời:

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

Tùy thuộc vào chức năng của bạn, bạn cũng có thể thoát / quay lại từ vòng lặp bên trong:

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

7
Tôi thấy cách này lộn xộn.
boutta

11
Một điều kiện bổ sung kiểm tra mỗi lần qua vòng lặp? Không, cám ơn.
ryandenki

15

Nếu bạn không thích breaks và gotos, bạn có thể sử dụng vòng lặp "truyền thống" thay vì for-in, với điều kiện hủy bỏ thêm:

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
Không phù hợp để vòng lặp foreach.
John McClane

1
@JohnMcClane Và bạn đang spam câu hỏi này trên nhiều câu trả lời cho câu hỏi trên 9 tuổi vì ...?
Quintec

12

Tôi cần phải làm một điều tương tự, nhưng tôi đã chọn không sử dụng vòng lặp for được tăng cường để làm điều đó.

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

Tôi không thấy tuyệt khi lặp lại tất cả các mục sau khi điều kiện bị hỏng. Vì vậy, tôi sẽ thêm một phá vỡ trong trường hợp khác.
boutta

@boutta Tôi không chắc bạn sẽ đạt được kết luận này như thế nào. Một khi điều kiện là đúng, cả hai vòng lặp được thoát.
Swifty McSwifterton

OK, tôi đã không nhận được một phần với sự thao túng của var. Nhưng tôi thấy kiểu đó không tốt vì s đại diện cho kích thước. Sau đó, tôi thích câu trả lời từ ddyer với các vars rõ ràng: stackoverflow.com/a/25124317/15108
boutta

@boutta Bạn có thể thay đổi sthành giá trị thấp hơn ihoặc thay đổi ithành giá trị lớn hơn hoặc bằng s, cả hai nên thực hiện thủ thuật. Bạn đúng về việc thay đổi s, bởi vì nó có thể được sử dụng ở nơi khác sau đó, nhưng việc thay đổi isẽ không gây hại, chỉ cần đảm bảo rằng lần đầu tiên forsẽ không tiếp tục lặp.
Zsolti

9

Tôi thích thêm một "lối thoát" rõ ràng vào các bài kiểm tra vòng lặp. Nó làm cho rõ ràng với bất kỳ độc giả bình thường rằng vòng lặp có thể chấm dứt sớm.

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

Không phù hợp để vòng lặp foreach.
John McClane

8

StreamGiải pháp 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 và vẫn hữu ích cho những người dùng khác, vì vậy các phương pháp và giải pháp mới luôn được chào đón
Andrei Suvorkov

Wow, thật là xấu xí.
DS.

7

Thông thường trong các trường hợp như vậy, nó xuất hiện trong phạm vi logic có ý nghĩa hơn, giả sử một số tìm kiếm hoặc thao tác trên một số đối tượng 'for'-iter được nhắc đến, vì vậy tôi thường sử dụng phương pháp chức năng:

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

Nhược điểm chính:

  • khoảng gấp đôi dòng
  • tiêu thụ nhiều hơn các chu kỳ tính toán, có nghĩa là nó chậm hơn từ quan điểm thuật toán
  • đánh máy nhiều hơn

Ưu điểm:

  • tỷ lệ cao hơn để phân tách các mối quan tâm vì độ chi tiết chức năng
  • tỷ lệ tái sử dụng và kiểm soát logic tìm kiếm / thao tác cao hơn mà không cần
  • các phương pháp không dài, do đó chúng nhỏ gọn hơn và dễ hiểu hơn
  • tỷ lệ dễ đọc cao hơn

Vì vậy, nó chỉ là xử lý trường hợp thông qua một cách tiếp cận khác.

Về cơ bản một câu hỏi cho tác giả của câu hỏi này: bạn nghĩ gì về phương pháp này?


6

Bạn có thể thoát khỏi tất cả các vòng mà không cần sử dụng bất kỳ nhãn nào: và cờ.

Đó chỉ là giải pháp khó khăn.

Ở đây condition1 là điều kiện được sử dụng để thoát khỏi vòng K và J. Và điều kiện2 là điều kiện được sử dụng để ngắt từ vòng K, J và I.

Ví dụ:

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
Làm thế nào tôi có thể sử dụng điều này với mỗi vòng lặp? ;)
Willi Mentzel

5
Điều này không hoạt động nếu bạn có một điều kiện vòng lặp phức tạp hơn, như list.size ()> 5. Ngoài ra nó thực sự chỉ là một hack. Thật khó để đọc và thực hành xấu!
Thần kinh

Nó dễ bị lỗi. Hãy tưởng tượng bạn đã thay đổi vòng lặp bên trong để (int k = 0; k < 10; k++)và bạn không khắc phục được tất cả các k = 9đến k = 10. Bạn có thể đi vào một vòng lặp vô hạn.
Florian F

5

Khái niệm phá vỡ được gắn nhãn được sử dụng để phá vỡ các vòng lặp lồng nhau trong java, bằng cách sử dụng ngắt có nhãn, bạn có thể phá vỡ các vòng lặp lồng nhau ở bất kỳ vị trí nào. Ví dụ 1:

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

giả sử có 3 vòng lặp và bạn muốn chấm dứt vòng lặp3: Ví dụ 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

Nếu nó nằm trong một số chức năng tại sao bạn không trả lại nó:

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

Tôi thích mẫu này. Nó thường khiến tôi phá vỡ các vòng lặp thành một chức năng riêng biệt. Mã của tôi luôn luôn tốt hơn sau khi làm như vậy, vì vậy vì lý do này tôi thực sự thích câu trả lời này.
Bill K

4

Phương pháp tốt nhất và dễ dàng ..

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
Những ví dụ về phá vỡ là imho không hữu ích lắm, bởi vì ngay cả khi không có nhãn họ cũng sẽ phá vỡ tại cùng một điểm. Ngoài ra, thật tuyệt khi có mã mà bạn thực sự có thể thực thi, đó không phải là trường hợp với mã của bạn, vì không bao giờ có thể đạt được mã bên trong ..
Neuron

Tôi sẽ gõ điều tương tự. Các nhãn là hơi vô dụng trong trường hợp này.
Taslim Oseni

4

Cách tiếp cận khá bất thường nhưng về độ dài mã ( không phải hiệu năng ) thì đây là điều dễ nhất bạn có thể làm:

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

Một giải pháp khác, được đề cập mà không có ví dụ (nó thực sự hoạt động trong mã 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.
}

Tất nhiên BreakLoopExceptionphải là nội bộ, riêng tư và được tăng tốc với không có dấu vết ngăn xếp:

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

1
Nó đã được đề cập thực sự, trong một câu trả lời nhận được -23 phiếu ... stackoverflow.com/a/886980/2516301 . Nó sẽ thực hiện công việc, nhưng đó là một thực hành lập trình rất tệ ...
vefthym

thật. tuy nhiên tôi thấy mã kế thừa như vậy - các vòng lặp lồng nhau 4 cấp với một số điều kiện phá vỡ. và nó dễ đọc hơn với các ngoại lệ thay vì mã nội tuyến. -23 phiếu bầu chủ yếu là đánh giá cảm xúc, nhưng có - cách tiếp cận này nên được sử dụng cẩn thận.
ursa

1
Nó thậm chí còn dễ đọc hơn nếu nó được chia thành một lệnh gọi chức năng riêng biệt với trung tâm trả về. Thường được làm tốt hơn bởi một bộ tái cấu trúc nhỏ để nó có ý nghĩa như là một hàm độc lập (thường có thể tái sử dụng).
Bill K

2

for (int j = 0; j < 5; j++) //inner loopnên được thay thế bằng for (int j = 0; j < 5 && !exitloops; j++).

Ở đây, trong trường hợp này, các vòng lặp lồng hoàn chỉnh sẽ được thoát nếu có điều kiện True. Nhưng nếu chúng ta exitloopschỉ sử dụng cho cấp trênloop

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

Sau đó, vòng lặp bên trong sẽ tiếp tục, bởi vì không có cờ bổ sung thông báo vòng lặp bên trong này để thoát.

Ví dụ: nếu i = 3j=2thì điều kiện là false. Nhưng trong phiên bản kế tiếp của vòng lặp bên trong j=3 sau đó tình trạng (i*j)trở nên 9đó là truenhưng vòng lặp bên trong sẽ được tiếp tục cho đến khi jtrở thành 5.

Vì vậy, nó cũng phải sử dụng exitloopscác vòng lặp bên trong.

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

Giống như đề xuất THÔNG TIN @ 1800, sử dụng điều kiện phá vỡ vòng lặp bên trong làm điều kiện ở vòng lặp bên ngoài:

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

Nếu đó là một triển khai mới, bạn có thể thử viết lại logic dưới dạng các câu lệnh if-other_if-other.

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

Nếu không, bạn có thể thử đặt cờ khi điều kiện đặc biệt đó xảy ra và kiểm tra cờ đó trong mỗi điều kiện vòng lặp của bạn.

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

ĐÂY! Vì vậy, trong khi nghỉ đơn giản sẽ không hoạt động, nó có thể được thực hiện để sử dụng continue.

Nếu bạn chỉ đơn giản chuyển logic từ một ngôn ngữ lập trình sang Java và chỉ muốn mọi thứ hoạt động, bạn có thể thử sử dụng nhãn .


2

Demo cho break, continuelabel:

Từ khóa Java breakcontinuecó một giá trị mặc định. Đó là "vòng lặp gần nhất" và hôm nay, sau vài năm sử dụng Java, tôi mới hiểu được!

Nó dường như được sử dụng hiếm, nhưng hữu ích.

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

Bản giới thiệu

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

1

Bạn có thể làm như sau:

  1. đặt một biến cục bộ thành false

  2. Đặt biến đó truetrong vòng lặp đầu tiên, khi bạn muốn ngắt

  3. sau đó bạn có thể kiểm tra trong vòng lặp bên ngoài, rằng liệu điều kiện được đặt sau đó cũng thoát khỏi vòng lặp bên ngoài.

    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

Đối với một số trường hợp, chúng ta có thể sử dụng whilevòng lặp hiệu quả ở đây.

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 không có tính năng goto như trong C ++. Nhưng vẫn gotolà một từ khóa dành riêng trong Java. Họ có thể thực hiện nó trong tương lai. Đối với câu hỏi của bạn, câu trả lời là có một cái gì đó được gọi là nhãn trong Java mà bạn có thể áp dụng một câu lệnh continuebreakcâu lệnh. Tìm mã dưới đây:

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

Thậm chí tạo một cờ cho vòng lặp bên ngoài và kiểm tra xem sau mỗi lần thực hiện vòng lặp bên trong có thể là câu trả lời.

Như thế này:

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

Sử dụng conditionlàm cờ khi bạn xử lý xong. Sau đó, vòng lặp bên trong chỉ tiếp tục trong khi điều kiện chưa được đáp ứng. Dù bằng cách nào, vòng lặp bên ngoài sẽ tiếp tục chuggin '.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.