提问人:boutta 提问时间:5/20/2009 最后编辑:Alireza Nooraliboutta 更新时间:4/9/2023 访问量:1405311
如何打破 Java 中的嵌套循环?
How do I break out of nested loops in Java?
问:
我有一个嵌套的循环结构,如下所示:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
}
现在我怎样才能打破这两个循环?我也研究过类似的问题,但没有一个是专门针对 Java 的。我无法应用这些解决方案,因为大多数人都使用 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
评论
您可以使用标签:
label1:
for (int i = 0;;) {
for (int g = 0;;) {
break label1;
}
}
您可以使用临时变量:
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;
}
}
}
您可以在循环周围使用命名块:
search: {
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break search;
}
}
}
}
评论
使用函数:
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;
}
}
}
}
从技术上讲,正确的答案是标记外环。在实践中,如果你想在内部循环内的任何一点退出,那么你最好将代码外部化到一个方法(如果需要的话,是一个静态方法),然后调用它。
这将为可读性带来回报。
代码将变成这样:
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);
}
}
}
}
评论
我从不使用标签。这似乎是一种不好的做法。这是我会做的:
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;
}
}
}
通过标志变量,我们可以很容易地控制任意数量的循环的执行,只是我们需要在循环条件语句中保持这个标志值检查,就像在 main loop->i < 5 && !finished 中所做的那样。
评论
我需要做类似的事情,但我选择不使用增强的 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;
}
}
}
评论
s
i
i
s
s
i
for
你只需使用标签来打破内部循环
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");
}
}
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;
}
}
如果你不喜欢 s 和 s,你可以使用“传统”的 for 循环来代替 for-in,并有一个额外的中止条件: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;
}
}
}
评论
您可以在不使用任何 label: 和 flags 的情况下中断所有循环。
这只是一个棘手的解决方案。
这里的 condition1 是用于中断循环 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");
}
}
评论
(int k = 0; k < 10; k++)
k = 9
k = 10
使用标签。
INNER:for(int j = 0; j < numbers.length; j++) {
System.out.println("Even number: " + i + ", break from INNER label");
break INNER;
}
请参阅此文章
评论
我更喜欢在循环测试中添加一个明确的“退出”。它清楚地表明 任何可能提前终止循环的普通读者。
boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
像@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;
}
}
}
另一个解决方案,在没有示例的情况下提到(它实际上适用于生产代码)。
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.
}
当然,应该是内部的、私有的,并使用 no-stack-trace 加速:BreakLoopException
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;
}
}
评论
通常在这种情况下,它属于更有意义的逻辑范围,比如说对一些迭代的“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;
}
主要缺点:
- 大约两倍以上的行
- 计算周期消耗更多,这意味着从算法的角度来看,它的速度更慢
- 更多打字工作
优点:
- 由于功能粒度,关注点分离的比率更高
- 可重用性和可控性比率更高 搜索/操作逻辑,无需
- 方法不长,因此更紧凑,更容易理解
- 更高的可读性
所以它只是通过不同的方法处理案件。
基本上是这个问题的作者的问题:您如何看待这种方法?
for (int j = 0; j < 5; j++) //inner loop
应替换为 。for (int j = 0; j < 5 && !exitloops; j++)
在这里,在这种情况下,如果条件是 ,则完整的嵌套循环应该退出。但是如果我们只使用鞋面True
exitloops
loop
for (int i = 0; i < 5 && !exitloops; i++) //upper loop
然后内部循环将继续,因为没有额外的标志通知这个内部循环退出。
示例:if 和 then 条件为 。但是在内循环的下一次迭代中,条件变为 which is 但内循环将继续直到 become 。
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);
}
}
如果它在某个函数中,为什么不直接返回它:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
return value;
}
}
}
评论
如果是新的实现,可以尝试将逻辑重写为 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
如果你只是将逻辑从一种编程语言移植到 Java 上,并且只想让它正常工作,你可以尝试使用标签。
演示 、 和 :break
continue
label
Java 关键字,并具有默认值。这是“最近的循环”,今天,在使用 Java 几年后,我刚刚掌握了它!break
continue
它似乎很少使用,但很有用。
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);
}
}
}
}
}
Java 8 Stream
解决方案:
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**/);
评论
您可以执行以下操作:
将局部变量设置为
false
在第一个循环中设置该变量,当您想要中断时
true
然后,您可以在外循环中检查条件是否设置,然后也从外循环中断。
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 } }
Java 没有像 C++ 那样的 goto 功能。但是,仍然是 Java 中的保留关键字。他们可能会在未来实施它。对于您的问题,答案是 Java 中有一种叫做 label 的东西,您可以将 and 语句应用于它。找到下面的代码:goto
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");
}
标记的中断概念用于在 java 中分解嵌套的循环,通过使用标记的中断,您可以在任何位置中断嵌套的循环。 示例 1:
loop1:
for(int i= 0; i<6; i++){
for(int j=0; j<5; j++){
if(i==3)
break loop1;
}
}
假设有 3 个循环,并且您想要终止 Loop3: 示例 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;
}
}
}
演示
public static void main(String[] args) {
outer:
while (true) {
while (true) {
break outer;
}
}
}
使用起来相当简单,可以使用标签将外循环从内部循环中分解开来,考虑下面的例子,label
public class Breaking{
public static void main(String[] args) {
outerscope:
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (condition) {
break outerscope;
}
}
}
}
}
另一种方法是使用中断变量/标志来跟踪所需的中断。请看以下示例。
public class Breaking{
public static void main(String[] args) {
boolean isBreaking = false;
for (int i=0; i < 5; i++) {
for (int j=0; j < 5; j++) {
if (condition) {
isBreaking = true;
break;
}
}
if(isBreaking){
break;
}
}
}
}
但是,我更喜欢使用第一种方法。
当您需要退出多个循环时,单独使用“break”关键字不是合适的方法。 您可以退出即时循环 不管你的语句被包围了多少个循环。 您可以将“break”与标签一起使用! 在这里,我使用了标签“abc” 您可以在 Java 中的任何函数中编写代码
此代码演示如何从最外层循环退出
abc:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break abc;
}
}
}
}
此外,还可以使用 break 语句从嵌套循环中的任何循环中退出。
for (int i = 0; i < 10; i++) {
abc:for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break abc;
}
}
}
}
以下代码显示了从最内层循环退出的示例。 在其他作品中,执行以下代码后,你处于“k”变量循环的外部,仍然在“j”和“i”变量的循环内。
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
for (int k = 0; k < 10; k++) {
if (k == 1){
break;
}
}
}
}
下一个:我需要帮助来创建此滑块结构
评论