在Java中打破嵌套循环
我有一个像这样的嵌套循环结构:
for (Type type : types) { for (Type t : types2) { if (some condition) { // Do something and break... break; // Breaks out of the inner loop } } }
现在我怎么能摆脱两个循环。 我看过类似的问题,但是没有一个关于Java的具体问题。 我不能应用这些解决scheme,因为大多数使用gotos。
我不想把内部循环放在一个不同的方法中。
更新:我不想重新运行循环,当打破我完成循环块的执行。
(编辑:和其他答案一样,我更希望把内部循环放在一个不同的方法中,这个答案只是说明了如何满足这个问题的要求。)
您可以使用外部循环的标签进行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
从技术上讲,正确的答案是标记外部循环。 在实践中,如果你想在内部循环中的任何一点退出,那么你最好把代码外部化成一个方法(如果需要,就是一个静态方法),然后调用它。
这将为可读性带来回报。
代码会变成这样的:
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); } } } }
你可以在循环中使用一个命名块:
search: { for (Type type : types) { for (Type t : types2) { if (some condition) { // Do something and break... break search; } } } }
我从来不使用标签。 这似乎是一个不好的做法,进入。 这是我会做的:
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; } } }
你可以使用标签:
label1: for (int i = 0;;) { for (int g = 0;;) { break label1; } }
也许有一个function?
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; } } } }
你可以使用一个临时variables:
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 } } }
根据你的function,你也可以退出/从内部循环返回:
for (Type type : types) { for (Type t : types2) { if (some condition) { // Do something and break... return; } } }
如果你不喜欢break
和goto
,那么你可以使用“传统”循环代替原来的循环,并且有一个额外的终止条件:
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; } } }
我需要做类似的事情,但我select不使用增强的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; } } }
我更喜欢在循环testing中添加一个明确的“退出”。 这让任何偶然的读者都清楚,循环可能会提前终止。
boolean earlyExit = false; for(int i=0;i<10&&!earlyExit; i++) { for(int j=0;i<10&&!earlyExit; j++) { earlyExit=true; } }
Java 8 Stream解决scheme:
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**/);
你可以打破所有的循环,而不使用任何标签:和标志。
这只是一个棘手的解决scheme。
这里condition1是用来从循环K和J中断开的条件。而condition2是用来从循环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"); } }
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; } }
像@ 1800信息build议一样,使用将内部循环作为外部循环条件的条件:
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; } } }
另一个解决scheme,没有例子提到(它实际上在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. }
当然,打破例外应该是内部的,私人的,加速的,没有堆栈跟踪:
private static class BreakLoopException extends Exception { @Override public StackTraceElement[] getStackTrace() { return new StackTraceElement[0]; } }
相当不寻常的方法,但在代码长度( 而不是性能 )方面,这是你可以做的最简单的事情:
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 } }
最简单的方法
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; } }
相当长一段时间,我想分享这种types的问题的答案types。
通常情况下,这种情况已经出现在一个更有意义的逻辑范围之内,比方说,我们可以通过search或操纵某些迭代的“for”对象,所以我通常使用函数式的方法:
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; }
主要缺点:
- 大概再多两行
- 计算周期的消耗更多,这意味着从algorithm的angular度来看它更慢
- 更多的打字工作
优点:
- 由于function粒度的关系分离率较高
- search/操作逻辑的可重用性和控制的比例较高
- 方法不长,因此更紧凑,更容易理解
- 主观性较高的可读性比例
所以这只是通过不同的方式来处理案件。
这个问题的作者基本上是一个问题:你如何看待这种方法?
使用标签。
INNER:for(int j = 0; j<numbers.length; j++){ System.out.println("Even number: " + i + ", break from INNER label"); break INNER; }
请参阅这篇文章http://javarevisited.blogspot.com/2012/05/break-continue-and-lablel-in-loop-java.html
甚至为外层循环创build一个标志并检查内层循环的每次执行之后都可以作为答案。
喜欢这个 :
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; }
如果它在某个函数里面,为什么不把它返回呢:
for (Type type : types) { for (Type t : types2) { if (some condition) { return value; } } }
for (int j = 0; j < 5; j++) //inner loop
应该replacefor (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
但是内循环将继续,直到j
变成5
。
所以,它也必须使用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); } }
我想回答这个问题,但被标记为重复,防止我发布以及。 所以张贴在这里,而不是!
如果它是一个新的实现,你可以尝试重写逻辑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) { // things below will not be executed continue; } // other things may happen here as well but will not be executed // once control is returned from the inner cycle } HERE! So, while a simple break will not work, it can be made to work using continue.
如果你只是简单地将一种编程语言的逻辑移植到java中,而只是想让这些东西起作用,那么你可以尝试使用标签
演示break continue lable
,所以java关键字“break continue”有默认值,这是“最近的循环”,使用Java几年后,我只是得到它!
这似乎很less见,但有用
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.)设置一个局部variables为false
2.)在第一个循环中设置variablestrue,当你想要分开时
3.)然后你可以检查外部循环,条件是否设置,然后从外部循环中断。
boolean isBreakNeeded= false; for(int i =0;i<some.length;i++) { for(int j=0;j<some.lengthasWell;j++){ if(//want to set variable){ isBreakNeeded=true; break; } if(isBreakNeeded){ break; //will make you break from outer loop as well } } }
对我来说这似乎是一个简单的方法。
对于一些情况,我们可以while
这里有效地使用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; }
你只是使用标签来打破内部循环
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"); } }
检查内部循环是否用if语句退出,通过检查内部循环的variables。 你也可以创build另外一个variables,如布尔值来检查内部循环是否退出。
在这个例子中,它使用内部循环的variables来检查它是否已经退出:
int i, j; for(i = 0; i < 7; i++){ for(j = 0; j < 5; j++) { if (some condition) { // Do something and break... break; // Breaks out of the inner loop } } if(j < 5){ // Checks if inner loop wasn't finished break; // Breaks out of the outer loop } }
boolean condition = false; for (Type type : types) { for (int i = 0; i < otherTypes.size && !condition; i ++) { condition = true; // if your condition is satisfied } }
当你完成处理时,使用条件作为标志。 然后内部循环只在条件未满足的情况下继续。 无论哪种方式外层循环将保持chuggin'。
我觉得使用标签使代码看起来非常像goto语句。 这只是一个想法。 为什么我们不在内循环中抛出exception,并用try catch块封装两个for循环。 就像是
try { ... for(Object outerForLoop : objectsOuter) { ... for (Object innerForLoop : objectsInner) { ... if (isConditionTrue) throw new WrappedException("With some useful message. Probably some logging as well."); } } catch (WrappedException) { // do something awesome or just don't do anything swallow the exception. }
只是一个想法。 我更喜欢这个代码,因为当它在生产中运行时,它给了我更好的可logging性(就像这个词)。