我有一个这样的嵌套循环结构:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
// Do something and break...
break; // Breaks out of the inner loop
}
}
}
现在我怎样才能打破这两个循环?我看过类似的问题,但没有一个特别关注 Java。我无法应用这些解决方案,因为大多数使用 goto。
我不想将内部循环放在不同的方法中。
我不想返回循环。中断时,我完成了循环块的执行。
像其他回答者一样,我肯定更喜欢将循环放在不同的方法中,此时您可以返回以完全停止迭代。该答案仅显示如何满足问题中的要求。
您可以将 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;
}
}
使用一个函数:
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;
}
}
}
}
您可以使用临时变量:
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;
}
}
}
如果您不喜欢 break
和 goto
,您可以使用“传统”的 for 循环代替 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;
}
}
}
当您需要退出多个循环时,单独使用“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;
}
}
}
}
我需要做类似的事情,但我选择不使用增强的 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
不会继续循环。
我更喜欢在循环测试中添加一个明确的“退出”。它使任何不经意的读者都清楚循环可能会提前终止。
boolean earlyExit = false;
for(int i = 0 ; i < 10 && !earlyExit; i++) {
for(int j = 0 ; i < 10 && !earlyExit; j++) { earlyExit = true; }
}
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**/);
带标签的break概念用于打破Java中的嵌套循环,通过使用带标签的break,您可以在任何位置打破循环的嵌套。示例 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;
}
}
}
通常在这种情况下,它会出现在更有意义的逻辑范围内,比如说对一些有问题的迭代“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;
}
主要缺点:
大约多行两倍
更多的计算周期消耗,这意味着从算法的角度来看它更慢
更多打字工作
优点:
由于功能粒度,关注点分离的比率更高
搜索/操作逻辑的可重用性和控制率更高
这些方法不长,因此它们更紧凑,更容易理解
更高的可读性
因此,它只是通过不同的方法处理此案。
基本上是向这个问题的作者提出的一个问题:您如何看待这种方法?
您可以在不使用任何标签的情况下中断所有循环:和标志。
这只是棘手的解决方案。
这里 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");
}
}
(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;
}
请参阅this article
最好最简单的方法..
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;
}
}
演示
public static void main(String[] args) {
outer:
while (true) {
while (true) {
break outer;
}
}
}
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;
}
}
如果它在某个函数中,为什么不直接返回它:
for (Type type : types) {
for (Type t : types2) {
if (some condition) {
return value;
}
}
}
相当不寻常的方法,但就代码长度(而不是性能)而言,这是您可以做的最简单的事情:
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
}
}
另一种解决方案,没有例子提到(它实际上在产品代码中工作)。
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
应该是内部的、私有的和加速的,没有堆栈跟踪:
private static class BreakLoopException extends Exception {
@Override
public StackTraceElement[] getStackTrace() {
return new StackTraceElement[0];
}
}
使用 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
、continue
和 label
的演示:
Java 关键字 break
和 continue
具有默认值。这是“最近的循环”,今天,在使用 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);
}
}
}
}
}
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
然后内部循环将继续,因为没有额外的标志通知这个内部循环退出。
示例:如果 i = 3 且 j=2 则条件为假。但在内循环 j=3 的下一次迭代中,条件 (i*j) 变为 9,这是真的,但内循环将继续,直到 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);
}
}
像@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;
}
}
}
Java 没有 C++ 中的 goto 功能。但是,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");
}
如果是新实现,可以尝试将逻辑重写为 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,并且只是想让它工作,您可以尝试使用 labels。
您只需使用标签来打破内部循环
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");
}
}
您可以执行以下操作:
将局部变量设置为 false 在第一个循环中将该变量设置为 true,当您想要中断时,您可以在外循环中检查是否设置了条件,然后也从外循环中断。布尔 isBreakNeeded = false; for (int i = 0; i < some.length; i++) { for (int j = 0; j < some.lengthasWell; j++) { //想要设置变量 if (){ isBreakNeeded = true;休息; } if (isBreakNeeded) { 休息; //也会让你跳出外循环 } }
不定期副业成功案例分享