как вырваться из вложенных циклов в java?

<p>у меня есть конструкция вложенного цикла, как это:</p><pre><code>for (type type : types) { for (type t : types2) { if (some condition) { // do something and break... break; // breaks out of the inner loop } } } </code></pre><p>теперь, как я могу вырваться из обеих петель? я смотрел на подобные вопросы, но ни один из них не касается конкретно java. я не мог применить эти решения, потому что большинство использовали gotos.</p><p>я не хочу помещать внутренний цикл в другой метод.</p><p>я не хочу повторять петли. при разрыве я заканчиваю выполнение цикла цикла.</p>

<p>как и другие ответчики, я бы определенно<em> предпочел </em>поместить циклы в другой метод, после чего вы можете просто вернуться, чтобы полностью прекратить итерации. этот ответ просто показывает, как требования в вопросе могут быть выполнены.</p><p>вы можете использовать <code>break</code> с меткой для внешнего цикла. например:</p><pre><code>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"); } } </code></pre><p>это печатает:</p><pre><code>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 </code></pre>

<p>технически правильный ответ - обозначить внешний цикл. на практике, если вы хотите выйти из любой точки во внутреннем цикле, вам лучше было бы перенести код в метод (статический метод, если это необходимо), а затем вызвать его.</p><p>это окупится за удобочитаемость. </p><p>код станет примерно таким: </p><pre><code>private static string search(...) { for (type type : types) { for (type t : types2) { if (some condition) { // do something and break... return search; } } } return null; } </code></pre><p>соответствие примеру для принятого ответа:</p><pre><code> 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); } } } } </code></pre>

<p>вы можете использовать именованный блок вокруг циклов:</p><pre><code>search: { for (type type : types) { for (type t : types2) { if (some condition) { // do something and break... break search; } } } } </code></pre>

<p>я никогда не использую ярлыки. кажется, это плохая практика. вот что я бы сделал:</p><pre><code>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; } } } </code></pre>

<p>вы можете использовать ярлыки:</p><pre><code>label1: for (int i = 0;;) { for (int g = 0;;) { break label1; } } </code></pre>

<p>используйте функцию:</p><pre><code>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; } } } } </code></pre>

<p>вы можете использовать временную переменную:</p><pre><code>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 } } } </code></pre><p>в зависимости от вашей функции вы также можете выйти/вернуться из внутреннего цикла:</p><pre><code>for (type type : types) { for (type t : types2) { if (some condition) { // do something and break... return; } } } </code></pre>

<p>если вам не нравятся <code>break</code>s и <code>goto</code>s, вы можете использовать «традиционный» цикл for вместо for-in с дополнительным условием прерывания:</p><pre><code>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; } } } </code></pre>

<p>мне нужно было сделать похожую вещь, но я решил не использовать расширенный цикл for, чтобы сделать это.</p><pre><code>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; } } } </code></pre>

<p>я предпочитаю добавить явный «выход» к тестам цикла. .... любому случайному читателю становится ясно, что цикл может завершиться досрочно.</p><pre><code>boolean earlyexit = false; for(int i = 0 ; i < 10 && !earlyexit; i++) { for(int j = 0 ; i < 10 && !earlyexit; j++) { earlyexit = true; } } </code></pre>

<p>java 8 <a href="https://docs.oracle.com/javase/8/docs/api/?java/util/stream/stream.html"><code>stream</code></a> решение:</p><pre><code>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**/); </code></pre>

<p>вы можете отрываться от всех циклов без использования меток: и флагов.</p><p>это просто хитрое решение.</p><p>здесь условие 1 - это условие, которое используется для разрыва цикла k и j . а условие 2 - это условие, которое используется для разрыва цикла k, j и i.</p><p>например:</p><pre><code>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"); } } </code></pre>

<p>обычно в таких случаях это входит в область более осмысленной логики, скажем, некоторого поиска или манипулирования некоторыми итеративными объектами for, о которых идет речь, поэтому я обычно использую функциональный подход:</p><pre><code>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; } </code></pre><p>основные минусы:</p><ul> <li>примерно в два раза больше строк</li> <li>больше потребления вычислительных циклов, что означает, что он медленнее с алгоритмической точки зрения</li> <li>больше печатать работу</li> </ul><p>плюсы:</p><ul> <li>более высокое отношение к разделению интересов из-за функциональной детализации</li> <li>более высокий коэффициент повторного использования и управления поиск/манипулирование логикой без</li> <li>методы не длинные, поэтому они более компактны и их легче понять</li> <li>субъективно более высокий коэффициент читабельности</li> </ul><p>так что это просто обработка дела с помощью другого подхода.</p><p>в основном вопрос к автору этого вопроса: что вы думаете об этом подходе?</p>

<p>лучший и простой метод ..</p><pre><code>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; } } </code></pre>

<p>если это внутри какой-то функции, почему бы вам просто не вернуть ее: </p><pre><code>for (type type : types) { for (type t : types2) { if (some condition) { return value; } } } </code></pre>

<p>довольно необычный подход, но с точки зрения длины кода (<strong> не производительности </strong>) это самое простое, что вы можете сделать:</p><pre><code>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 } } </code></pre>

<p>используйте ярлыки.</p><pre><code>inner:for(int j = 0; j < numbers.length; j++) { system.out.println("even number: " + i + ", break from inner label"); break inner; } </code></pre><p>обратитесь к <a href="http://[http://javarevisited.blogspot.com/2012/05/break-continue-and-lablel-in-loop-java.html][1]">эта статья</a> </p>

<p>еще одно решение, упомянутое без примера (на самом деле оно работает в коде prod).</p><pre><code>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. } </code></pre><p>конечно, <code>breakloopexception</code> должен быть внутренним, частным и ускоренным без отслеживания стека:</p><pre><code>private static class breakloopexception extends exception { @override public stacktraceelement[] getstacktrace() { return new stacktraceelement[0]; } } </code></pre>

<p>демонстрация для <code>break</code>, <code>continue</code> и <code>label</code>:</p><p>ключевые слова java <code>break</code> и <code>continue</code> имеют значение по умолчанию. это «ближайший цикл», и сегодня, после нескольких лет использования java, я только что понял!</p><p>кажется, используется редко, но полезно.</p><pre><code>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); } } } } } </code></pre>

<p><code>for (int j = 0; j < 5; j++) //inner loop</code> следует заменить на <code>for (int j = 0; j < 5 && !exitloops; j++)</code>.</p><p>здесь, в этом случае завершенные вложенные циклы должны быть завершены, если условие <code>true</code>. но если мы используем <code>exitloops</code> только для верхнего <code>loop</code> </p><pre><code> for (int i = 0; i < 5 && !exitloops; i++) //upper loop </code></pre><p>затем внутренний цикл продолжится, потому что нет никакого дополнительного флага, который уведомит этот внутренний цикл о выходе. </p><blockquote> <p>пример: если <code>i = 3</code> и <code>j=2</code>, то условие <code>false</code>. но в следующей итерации внутреннего цикла <code>j=3</code> тогда условие <code>(i*j)</code> становится <code>9</code>, которое является <code>true</code>, но внутренний цикл будет продолжаться до тех пор, пока <code>j</code> не станет <code>5</code>.</p> </blockquote><p>таким образом, он также должен использовать <code>exitloops</code> для внутренних циклов.</p><pre><code>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); } } </code></pre>

<p>как и предложение @ 1800 information, используйте условие, которое разрывает внутренний цикл, как условие на внешний цикл:</p><pre><code>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; } } } </code></pre>

<pre><code>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; } } </code></pre>

<p>если это новая реализация, вы можете попробовать переписать логику в виде операторов if-else\_if-else.</p><pre><code>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 } } </code></pre><p>в противном случае вы можете попробовать установить флаг, когда это специальное условие произошло, и проверить его в каждом из ваших условий цикла.</p><pre><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. } </code></pre><p>вот! таким образом, хотя простой перерыв не будет работать, его можно заставить работать с помощью <code>continue</code>.</p><p>если вы просто переносите логику с одного языка программирования на java и просто хотите, чтобы все работало, вы можете попробовать использовать <a href="https://stackoverflow.com/questions/26430630/how-to-use-goto-statement-correctly">label</a> .</p>

<p><strong> помеченный разрыв </strong>concept используется для разрыва вложенных циклов в java, используя помеченный разрыв, вы можете разорвать вложение циклов в любой позиции. пример 1:</p><pre><code>loop1: for(int i= 0; i<6; i++){ for(int j=0; j<5; j++){ if(i==3) break loop1; } } </code></pre><p>предположим, что есть 3 цикла, и вы хотите завершить цикл 3: пример 2:</p><pre><code>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; } } } </code></pre>

<p>вы можете сделать следующее:</p><ol> <li><p>установите локальную переменную в <code>false</code></p></li> <li><p>установите эту переменную <code>true</code> в первом цикле, когда вы хотите прервать</p></li> <li><p>тогда вы можете проверить во внешнем цикле, что если условие установлено, то и выход из внешнего цикла также будет выполнен.</p> <pre><code>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 } } </code></pre></li> </ol>

<p>в некоторых случаях мы можем эффективно использовать цикл <code>while</code> здесь.</p><pre><code>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; } </code></pre>

<p>даже создание флага для внешнего цикла и проверка того, что после каждого выполнения внутреннего цикла может быть ответом.</p><p>как это:</p><pre><code>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; } </code></pre>

<p>ниже приведен пример, где оператор «break» выталкивает курсор из цикла for всякий раз, когда выполняется условие.</p><pre><code>public class practice3\_findduplicatenumber { public static void main(string[] args) { integer[] inp = { 2, 3, 4, 3, 3 }; integer[] aux\_arr = new integer[inp.length]; boolean isduplicate = false; for (int i = 0; i < aux\_arr.length; i++) { aux\_arr[i] = -1; } outer: for (int i = 0; i < inp.length; i++) { if (aux\_arr[inp[i]] == -200) { system.out.println("duplicate found at index: " + i + " carrying value: " + inp[i]); isduplicate = true; break outer; } else { aux\_arr[inp[i]] = -200; } } for (integer integer : aux\_arr) { system.out.println(integer); } if (isduplicate == false) { system.out.println("no duplicates!!!!!"); } else { system.out.println("duplicates!!!!!"); } } } </code></pre>

<p>в java нет функции перехода, как в c++. но все же, <code>goto</code> является зарезервированным ключевым словом в java. они могут реализовать это в будущем. на ваш вопрос ответ таков: в java есть нечто, называемое меткой, к которой вы можете применить операторы <code>continue</code> и <code>break</code>. найдите код ниже:</p><pre><code>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"); } </code></pre>

<pre><code>boolean condition = false; for (type type : types) { for (int i = 0; i < othertypes.size && !condition; i ++) { condition = true; // if your condition is satisfied } } </code></pre><p>используйте <code>condition</code> в качестве флага, когда вы закончите обработку. тогда внутренний цикл только продолжается, пока условие не было выполнено. в любом случае, внешний цикл будет продолжать chuggin '.</p>