ฉันจะแยกลูปซ้อนกันใน Java ได้อย่างไร


1818

ฉันมีโครงสร้างวนซ้อนกันเช่นนี้:

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

ตอนนี้ฉันจะแยกลูปทั้งสองออกได้อย่างไร ฉันได้ดูคำถามที่คล้ายกัน แต่ไม่มีใครกังวล Java โดยเฉพาะ ฉันใช้โซลูชันเหล่านี้ไม่ได้เพราะ gotos ที่ใช้มากที่สุด

ฉันไม่ต้องการใส่วนรอบในวิธีอื่น

ฉันไม่ต้องการวิ่งวนซ้ำ เมื่อแตกฉันทำเสร็จแล้วด้วยการดำเนินการบล็อกลูป

คำตอบ:


2427

เช่นเดียวกับผู้ตอบคนอื่น ๆ ฉันชอบแน่นอนที่จะนำลูปในวิธีการที่แตกต่างกันที่จุดที่คุณก็สามารถกลับไปหยุด iterating สมบูรณ์ คำตอบนี้แสดงให้เห็นว่าข้อกำหนดในคำถามนั้นเป็นไปได้อย่างไร

คุณสามารถใช้breakกับป้ายกำกับสำหรับวงรอบนอก ตัวอย่างเช่น:

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 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
สิ่งนี้จะข้ามไปหลังจากลูปโดยตรง ลองมัน! ใช่ป้ายกำกับมาก่อนห่วง แต่นั่นเป็นเพราะป้ายกำกับของวงแทนที่จะเป็นสถานที่ที่คุณต้องการออก (คุณสามารถดำเนินการกับป้ายกำกับต่อไปได้)
Jon Skeet

2
Perl ยังอนุญาตให้มีระบบฉลากของตัวเอง ฉันคิดว่ามีหลายภาษาที่ทำ - มันแทบจะไม่ทำให้ฉันประหลาดใจว่าเป็นภาษาจาวา
Evan Carroll

9
@Evan - การอ้างสิทธิ์นั้นชัดเจนจริง - ในภาษาที่สัญญาว่าเป็นจริง แต่จาวาไม่ได้ทำตามสัญญา หากภาษามีความขัดแย้งกับสมมติฐานของคุณอาจเป็นไปได้ว่าเป็นสมมติฐานของคุณที่มีความผิด ในกรณีนี้ฉันคิดว่าคุณยังคงถูกต้องส่วนหนึ่ง - หลักการที่น่าประหลาดใจอย่างน้อยก็คือ WRT สำหรับคนที่ไม่เคยได้ยิน (หรือลืม) ในรูปแบบbreakนั้น ถึงอย่างนั้นข้อยกเว้นก็เป็นอีกข้อยกเว้นที่รู้จักกันดี (ขออภัย) แต่ฉันยังคงไม่พอใจเกี่ยวกับสิ่งนี้หากมันไม่ชัดเจน (ลูปขนาดเล็กแสดงความคิดเห็นเตือนหากฉลาก / ตัวแบ่งยังไม่ปรากฏให้เห็นเพียงพอ)
Steve314

6
@MuhammadBabar: outerloopเป็นป้ายกำกับ ฉันไม่รู้รหัสที่คุณพยายามอย่างแน่นอน แต่รหัสในคำตอบของฉันรวบรวมและทำงานได้ดี
Jon Skeet

4
@NisargPatil เพียงเพราะมันอยู่ใน sonarLint ไม่ได้ทำให้มันมีกลิ่นรหัส มันหมายความว่ามีนักพัฒนาที่เพิ่มสิ่งนี้ลงใน sonarLint พร้อมคันส่วนบุคคลเพื่อเกาและมันเต็มไปด้วยกฎเหล่านี้ที่เหมาะสมเมื่อถูกทารุณกรรมหรือเพราะผู้พัฒนาบางคนมีความเกลียดชังส่วนตัวที่ต่อต้านพวกเขา การแบ่งป้ายกำกับและดำเนินการต่อเป็นวิธีที่ยอดเยี่ยมในการอธิบายสิ่งที่คุณต้องการทำ
john16384

402

ในทางเทคนิคคำตอบที่ถูกต้องคือการติดป้ายวนรอบนอก ในทางปฏิบัติหากคุณต้องการออกที่จุดใด ๆ ภายในวงภายในแล้วคุณจะดีกว่าการส่งรหัสภายนอกออกเป็นวิธีการ (วิธีคงที่ถ้าจำเป็นต้องมี) แล้วเรียกมันว่า

ที่จะชำระสำหรับการอ่าน

รหัสจะกลายเป็นอะไรแบบนั้น:

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

จับคู่ตัวอย่างสำหรับคำตอบที่ยอมรับ:

 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
บางครั้งคุณใช้ตัวแปรท้องถิ่นหลายตัวที่อยู่นอกลูปด้านในการผ่านตัวแปรเหล่านั้นไปทั้งหมดจะทำให้รู้สึกอึดอัด
Haoest

1
ดังนั้นวิธีแก้ปัญหานี้ควรจะพิมพ์ "เสร็จสิ้น" ในคำตอบที่ยอมรับได้อย่างไร
JohnDoe

1
@JohnDoe คุณเรียกมันแล้วคุณพิมพ์ System.out.println ("เสร็จสิ้น"); ลอง {} ในที่สุด {} ในวิธีการค้นหาก็เป็นตัวเลือกเช่นกัน
Zo72

2
นี่เป็นแนวปฏิบัติที่ดีกว่าที่ฉันคาดเดา แต่จะเกิดอะไรขึ้นถ้าคุณต้องการทำต่อไปแทนที่จะทำลาย ฉลากสนับสนุนอย่างเท่าเทียมกัน (หรือไม่ดี!) แต่ฉันไม่แน่ใจว่าจะแปลงตรรกะนี้เพื่อดำเนินการต่อได้อย่างไร
Rob Grant

@RobertGrant หากคุณต้องการดำเนินการต่อแทนที่จะหยุดพักให้ย้ายลูปภายนอกนอกloopเมธอดและกลับจากเมธอดเพื่อดำเนินการต่อ
Muhd

215

คุณสามารถใช้บล็อกที่มีชื่อรอบลูป:

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

40
คุณไม่จำเป็นต้องสร้างบล็อกใหม่เพื่อใช้ป้ายกำกับ
Jon Skeet

81
ไม่ แต่มันทำให้ความตั้งใจชัดเจนขึ้น ดูความคิดเห็นแรกเกี่ยวกับคำตอบที่ยอมรับได้
Bombe

2
มันไม่ใช่บล็อกที่ตั้งชื่อตามจริงหลังจากป้ายกำกับคุณสามารถเขียนนิพจน์ Java ใด ๆ ที่ไม่มีป้ายกำกับname: if(...){...}ทำให้มีเงื่อนไขที่กำหนดหรือไม่ :)
La VloZ Merrill

4
โครงสร้างนี้มีข้อได้เปรียบที่สำคัญมากกว่าการติดฉลากforโดยตรง คุณสามารถเพิ่มรหัสก่อนหน้าสุดท้าย}ที่จะถูกดำเนินการเฉพาะในกรณีที่ไม่ตรงตามเงื่อนไข
Florian F

2
มันเป็นบล็อกที่มีชื่อและไม่ใช่การวนซ้ำที่มีชื่อ คุณไม่สามารถอยู่ในลูปนั้น "ค้นหาต่อไป" ซึ่งเป็นไวยากรณ์ทางกฎหมายโดยสมบูรณ์หากลูปมีชื่อว่าการค้นหา คุณสามารถทำลายมันได้ แต่คุณไม่สามารถดำเนินการต่อได้
Tatarize

132

ฉันไม่เคยใช้ฉลาก ดูเหมือนจะเป็นการฝึกฝนที่ไม่ดี นี่คือสิ่งที่ฉันจะทำ:

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
ไม่ควรนี้จะ&& !finishedแทน|| !finished? แล้วทำไมต้องใช้breakเลยและไม่ใช้&& !finishedกับห่วงด้านในด้วย?
แกนดัล์ฟ

4
ฉันใช้breakเพื่อให้สามารถออกจากวงโดยพลการ หากมีรหัสหลังจากifบล็อกนั้นคุณสามารถทำได้breakก่อนที่จะดำเนินการ &&แต่คุณต้องเกี่ยวกับ ซ่อมมัน.
Elle Mundy

2
ทางออกที่ดี! นั่นเป็นวิธีที่ฉันจะทำในทางปฏิบัติถ้าวางไว้ในฟังก์ชั่นพิเศษนั้นไม่เหมาะสำหรับบางเหตุผล
benroth

6
มีปัญหาที่อาจเกิดขึ้นหากมีตรรกะบางอย่างหลังจากวงใน ... ซึ่งจะยังคงได้รับการดำเนินการและวงด้านนอกแบ่งเฉพาะเมื่อการทำซ้ำใหม่เริ่มต้น ...
Karthik Karuppannan

7
ฉันไม่เข้าใจว่าทำไมเราควรทำเช่นนั้น ผู้ที่ทำงานกับรหัสควรสามารถใช้คุณลักษณะทั้งหมดของภาษาได้ ฉันเข้าใจว่ามันเป็นสิ่งสำคัญที่จะต้องเขียนโค้ดที่คนอื่นเข้าใจ แต่ไม่ใช่ด้วยการ จำกัด การใช้เครื่องมือที่เป็นทางการซึ่งจัดทำโดยภาษาและหาวิธีแก้ไขสำหรับการทำงานแบบเดียวกัน หรือคุณหมายถึงอย่างอื่นโดย "การปฏิบัติที่ไม่ดี"?
codepleb

107

คุณสามารถใช้ป้ายกำกับ:

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

4
มี +1 จากฉัน ง่ายตรงประเด็นตอบคำถาม ไม่สามารถถูกกล่าวหาว่าทำซ้ำคำตอบที่มีอยู่เพราะคุณตอบในเวลาเดียวกัน
Heimdall

40

ใช้ฟังก์ชั่น:

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

คุณสามารถใช้ตัวแปรชั่วคราว:

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

ขึ้นอยู่กับฟังก์ชั่นของคุณคุณสามารถออก / กลับจากวงใน:

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

7
ฉันพบว่าวิธีนี้รก
boutta

11
ตรวจสอบสภาพพิเศษทุกครั้งที่ผ่านลูปหรือไม่ ไม่เป็นไรขอบคุณ.
ryandenki

15

หากคุณไม่ชอบbreaks และgotos คุณสามารถใช้ "ดั้งเดิม" สำหรับลูปแทน for-in โดยมีเงื่อนไขการยกเลิกพิเศษ:

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
ไม่เหมาะที่จะใส่ลูป
John McClane

1
@JohnMcClane และคุณสแปมในหลาย ๆ คำตอบสำหรับคำถามอายุ 9 ปีเพราะ ...
Quintec

12

ฉันต้องการทำสิ่งที่คล้ายกัน แต่ฉันเลือกที่จะไม่ใช้การปรับปรุงสำหรับการวนซ้ำเพื่อทำ

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

ฉันไม่พบว่ามันยอดเยี่ยมในการวนซ้ำรายการทั้งหมดหลังจากที่สภาพเสีย ดังนั้นฉันจะเพิ่มตัวแบ่งในกรณีอื่น
บูทตา

@boutta ฉันไม่แน่ใจว่าคุณจะบรรลุข้อสรุปนี้ได้อย่างไร เมื่อเงื่อนไขเป็นจริงลูปทั้งคู่จะถูกออก
Swifty McSwifterton

ตกลงฉันไม่ได้มีส่วนร่วมกับการจัดการ var 's' แต่ฉันพบว่าสไตล์ที่ไม่ดีตั้งแต่ s แทนขนาด จากนั้นฉันชอบคำตอบจาก ddyer ด้วย vars อย่างชัดเจน: stackoverflow.com/a/25124317/15108
boutta

@boutta คุณสามารถเปลี่ยนsเป็นค่าที่ต่ำกว่าiหรือเปลี่ยนiเป็นค่าที่มากกว่าหรือเท่ากับกว่าได้sซึ่งทั้งคู่ควรทำเคล็ดลับ คุณถูกต้องเกี่ยวกับการเปลี่ยนแปลงsเนื่องจากสามารถใช้งานที่อื่นได้ในภายหลัง แต่การเปลี่ยนแปลงiจะไม่เป็นอันตรายเพียงตรวจสอบให้แน่ใจก่อนว่าforจะไม่วนลูปต่อไป
Zsolti

9

ฉันต้องการเพิ่ม "exit" อย่างชัดเจนในการทดสอบลูป ทำให้ชัดเจนกับผู้อ่านทั่วไปที่ลูปอาจยุติในช่วงต้น

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

ไม่เหมาะที่จะใส่ลูป
John McClane

8

Streamโซลูชัน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 และยังคงมีประโยชน์สำหรับผู้ใช้รายอื่นดังนั้นวิธีการและโซลูชั่นใหม่ ๆ ยินดีต้อนรับเสมอ
Andrei Suvorkov

ว้าวนั่นน่าเกลียด
DS

7

โดยทั่วไปในกรณีเช่นนี้มันกำลังอยู่ในขอบเขตของตรรกะที่มีความหมายมากกว่าสมมติว่ามีการค้นหาหรือจัดการบางส่วนของ 'for'-objects ที่มีปัญหาซ้ำดังนั้นฉันมักจะใช้วิธีการทำงาน:

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

ข้อเสียที่สำคัญ:

  • ประมาณสองบรรทัดมากขึ้น
  • ใช้รอบการคำนวณมากขึ้นซึ่งหมายความว่าช้าลงจากมุมมองของอัลกอริทึม
  • งานพิมพ์อื่น ๆ

ข้อดี:

  • อัตราส่วนที่สูงขึ้นต่อการแยกความกังวลเนื่องจากความละเอียดของฟังก์ชัน
  • อัตราส่วนที่สูงขึ้นของการใช้งานใหม่และการควบคุมการค้นหา / จัดการกับตรรกะโดยไม่ต้อง
  • วิธีการไม่นานจึงมีขนาดกะทัดรัดและง่ายต่อการเข้าใจ
  • อัตราส่วนที่สูงขึ้นของการอ่าน

ดังนั้นจึงเป็นเพียงการจัดการกรณีผ่านวิธีการที่แตกต่างกัน

โดยพื้นฐานแล้วคำถามกับผู้เขียนคำถามนี้: คุณคิดว่าแนวทางนี้เป็นอย่างไร?


6

คุณสามารถแยกจากลูปทั้งหมดได้โดยไม่ต้องใช้ป้ายกำกับและธงใด ๆ

มันเป็นทางออกที่ยุ่งยาก

นี่เงื่อนไข 1 คือเงื่อนไขที่ใช้ในการแยกจากลูป K และ J และเงื่อนไข 2 คือเงื่อนไขที่ใช้เพื่อแยกจากลูป K, J และ I

ตัวอย่างเช่น:

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
ฉันจะใช้สิ่งนี้กับแต่ละลูปได้อย่างไร ;)
Willi Mentzel

5
วิธีนี้ใช้ไม่ได้หากคุณมีเงื่อนไขลูปที่ซับซ้อนกว่าเช่น list.size ()> 5 นอกจากนี้มันเป็นเพียงแฮ็ค มันอ่านยากและฝึกหัดไม่ดี!
เซลล์ประสาท

มันเป็นข้อผิดพลาดได้ง่าย ลองนึกภาพคุณเปลี่ยนแปลงภายในวงไป(int k = 0; k < 10; k++)และคุณไม่สามารถแก้ไขทั้งหมดของการk = 9 k = 10คุณอาจเข้าสู่วงวนไม่สิ้นสุด
Florian F

5

แบ่งที่มีป้ายกำกับแนวคิดที่ใช้ในการแยกออกจากลูปซ้อนกันใน java โดยใช้ป้ายกำกับพักคุณสามารถทำลายรังของลูปที่ตำแหน่งใด ๆ ตัวอย่างที่ 1:

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

สมมติว่ามี 3 ลูปและคุณต้องการยุติลูป 3: ตัวอย่างที่ 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

หากอยู่ในฟังก์ชั่นบางอย่างทำไมคุณไม่ส่งคืนมัน

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

ฉันชอบรูปแบบนี้ บ่อยครั้งที่ทำให้ฉันแยกลูปออกเป็นฟังก์ชันแยกต่างหาก รหัสของฉันดีขึ้นเสมอหลังจากทำเช่นนั้นด้วยเหตุนี้ฉันชอบคำตอบนี้จริงๆ
Bill K

4

วิธีที่ดีที่สุดและง่าย ..

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
ตัวอย่างการทำลายเหล่านี้ไม่เป็นประโยชน์มากนักแม้กระทั่งหากไม่มีป้ายกำกับพวกเขาก็จะแตกหักในจุดเดียวกัน นอกจากนี้ยังเป็นเรื่องดีที่จะมีรหัสที่คุณสามารถใช้งานได้จริงซึ่งไม่ใช่กรณีของรหัสของคุณเนื่องจากไม่สามารถเข้าถึง
Innerloop

ฉันกำลังจะพิมพ์สิ่งเดียวกัน ฉลากค่อนข้างไร้ประโยชน์ในกรณีนี้
Taslim Oseni

4

วิธีการที่ผิดปกติ แต่ในแง่ของความยาวโค้ด ( ไม่ใช่ประสิทธิภาพ ) นี่คือสิ่งที่ง่ายที่สุดที่คุณสามารถทำได้:

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

อีกโซลูชันหนึ่งที่กล่าวถึงโดยไม่มีตัวอย่าง (ใช้งานได้จริงในรหัส 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.
}

แน่นอนBreakLoopExceptionควรเป็นภายในส่วนตัวและเร่งด้วย no-stack-trace:

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

1
จะได้รับการกล่าวถึงจริงในคำตอบที่ได้รับคะแนนโหวต -23 ... stackoverflow.com/a/886980/2516301 มันจะทำงาน แต่มันเป็นวิธีการเขียนโปรแกรมที่ดีมาก ...
vefthym

จริง แต่ฉันเห็นรหัสดั้งเดิมเช่น - ลูปซ้อนกัน 4 ระดับพร้อมเงื่อนไขแตกหักหลายอย่าง และมันสามารถอ่านได้โดยมีข้อยกเว้นมากกว่าด้วยโค้ดแบบอินไลน์ -23 คะแนนโหวตเป็นคะแนนด้านอารมณ์ส่วนใหญ่ แต่ใช่ - วิธีนี้ควรใช้อย่างระมัดระวัง
ursa

1
มันจะสามารถอ่านได้มากยิ่งขึ้นหากถูกแบ่งออกเป็นการเรียกฟังก์ชันที่แยกจากกันโดยมีการคืนศูนย์ บ่อยครั้งที่ทำให้ดียิ่งขึ้นโดย refactor เล็ก ๆ น้อย ๆ ดังนั้นจึงทำให้รู้สึกว่าเป็นฟังก์ชั่นแบบสแตนด์อโลน (มักจะนำมาใช้ซ้ำ)
Bill K

2

for (int j = 0; j < 5; j++) //inner loopfor (int j = 0; j < 5 && !exitloops; j++)จะถูกแทนที่ด้วย

Trueที่นี่ในกรณีนี้ลูปซ้อนกันที่สมบูรณ์แบบที่ควรจะเป็นทางออกถ้าเงื่อนไขเป็น แต่ถ้าเราใช้ exitloopsเฉพาะส่วนบนloop

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

จากนั้นลูปภายในจะดำเนินต่อไปเนื่องจากไม่มีแฟล็กพิเศษที่แจ้งเตือนลูปนี้เพื่อออก

ตัวอย่าง: ถ้าi = 3และแล้วสภาพเป็นj=2 falseแต่ในการย้ำต่อไปของวงด้านในj=3 แล้วสภาพ(i*j)กลายเป็น9ซึ่งเป็นtrueแต่ห่วงด้านในจะได้รับการดำเนินการต่อจนกลายเป็นj5

ดังนั้นมันต้องใช้exitloopsกับลูปด้านในด้วย

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

เช่นเดียวกับข้อเสนอแนะ @ 1800 INFORMATION ใช้เงื่อนไขที่แบ่งลูปด้านในเป็นเงื่อนไขในลูปด้านนอก:

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

หากเป็นการติดตั้งใหม่คุณสามารถลองเขียนตรรกะเป็นคำสั่ง 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
    }
}

มิฉะนั้นคุณสามารถลองตั้งค่าสถานะเมื่อเงื่อนไขพิเศษนั้นเกิดขึ้นและตรวจสอบการตั้งค่าสถานะนั้นในแต่ละเงื่อนไขลูปของคุณ

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

นี่! ดังนั้นในขณะที่การหยุดพักที่เรียบง่ายจะไม่ทำงาน แต่ก็สามารถใช้งานcontinueได้

หากคุณเป็นเพียงการ porting ตรรกะจากการเขียนโปรแกรมภาษาจาวาและเพียงแค่ต้องการที่จะได้รับสิ่งที่ทำงานคุณสามารถลองใช้ฉลาก


2

การสาธิตbreak, continueและlabel:

คำหลัก Java breakและcontinueมีค่าเริ่มต้น มันคือ "loop ที่ใกล้ที่สุด" และวันนี้หลังจากใช้ Java ไปสองสามปีฉันเพิ่งได้รับมัน!

ดูเหมือนจะใช้ยาก แต่มีประโยชน์

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


1

คุณสามารถทำสิ่งต่อไปนี้:

  1. ตั้งค่าตัวแปรท้องถิ่นเป็น false

  2. ตั้งค่าตัวแปรนั้นtrueในลูปแรกเมื่อคุณต้องการที่จะทำลาย

  3. จากนั้นคุณสามารถตรวจสอบในลูปด้านนอกว่าเงื่อนไขถูกตั้งค่าแล้วแตกออกจากลูปด้านนอกเช่นกัน

    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

สำหรับบางกรณีเราสามารถใช้การwhileวนซ้ำได้อย่างมีประสิทธิภาพที่นี่

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 ไม่มีคุณสมบัติข้ามไปเช่นที่มีใน C ++ แต่ก็ยังgotoเป็นคำหลักที่สงวนไว้ใน Java พวกเขาอาจใช้มันในอนาคต สำหรับคำถามของคุณคำตอบคือมีสิ่งที่เรียกว่าป้ายกำกับใน Java ซึ่งคุณสามารถใช้continueและbreakคำสั่ง ค้นหารหัสด้านล่าง:

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

แม้แต่การสร้างแฟล็กสำหรับลูปด้านนอกและตรวจสอบว่าหลังจากการดำเนินการของลูปภายในแต่ละครั้งสามารถเป็นคำตอบได้

แบบนี้:

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

ใช้conditionเป็นธงสำหรับเมื่อคุณเสร็จสิ้นการประมวลผล จากนั้นลูปด้านในจะทำงานต่อไปในขณะที่ไม่ได้ปฏิบัติตามเงื่อนไข ไม่ว่าจะด้วยวิธีใดวงรอบนอกจะยังคงอยู่บน chuggin '

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.