关于java:如何打破多个foreach循环?

How do I break multiple foreach loops?

本问题已经有最佳答案,请猛点这里访问。

我有四个foreach循环,它们遍历集合,并根据条件执行一些操作。

这是我现在写的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
boolean breakFlag = false;
String valueFromObj2 = null;
String valueFromObj4 = null;
for(Object1 object1: objects){
  for(Object2 object2: object1){
    // I get some value from object2
    valueFromObj2 = object2.getSomeValue();
    for(Object3 object3 : object2){
      for(Object4 object4: object3){
       // Finally I get some value from Object4.
       valueFromObj4 = object4.getSomeValue();
       // Compare with valueFromObj2 to decide either to break all the foreach loop
       breakFlag = compareTwoVariable(valueFromObj2, valueFromObj4 );
       if(breakFlag){break;}
      } // fourth loop ends here
      if(breakFlag){break;}
    } // third loop ends here
    if(breakFlag){break;}
  } // second loop ends here
  if(breakFlag){break;}
} // first loop ends here

主对象(代码中的对象)来自第三方提供程序SDK,因此我不能更改该部分的任何内容。我想问堆栈溢出社区是否有更好的方法来打破所有四个foreach循环。或者,如果有任何其他方法可以重构此代码,使其更易于阅读和维护。


在最外面的循环上使用一个标签,当您想跳出所有循环时,将这个标签包含在break语句中。在下面的示例中,我修改了您的代码以使用标签OUTERMOST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
String valueFromObj2 = null;
String valueFromObj4 = null;
OUTERMOST: for(Object1 object1: objects){
  for(Object2 object2: object1){
    //I get some value from object2
    valueFromObj2 = object2.getSomeValue();
    for(Object3 object3 : object2){
      for(Object4 object4: object3){
        //Finally I get some value from Object4.
        valueFromObj4 = object4.getSomeValue();
        //Compare with valueFromObj2 to decide either to break all the foreach loop
        if( compareTwoVariable(valueFromObj2, valueFromObj4 )) {
          break OUTERMOST;
        }
      }//fourth loop ends here
    }//third loop ends here
  }//second loop ends here
}//first loop ends here


将所有循环提取到函数中并使用返回。


可以使用带标签的break语句。这种中断终止了外部语句

参见break语句


您的示例非常通用,所以很难说是怎么回事,但是我从您提供的代码中得到了一种强烈的代码味道,我不得不认为必须有另一种方法来完成这项工作,最有可能的方法是将实际的数据结构重构为更有意义的内容。

什么样的清单objects是?它还包含哪些其他(最可能重要的)数据?如果不是太麻烦的话,我希望您能提供更相关的代码,因为我的重构器看到那堆循环就变得头晕目眩了。


使用一个标签,可以看到最简单的分支语句Java教程。您可以标记任意或所有for循环,然后将breakcontinue与这些标签一起使用。

使用标签的另一种选择是使用return。只需将代码重构为一个方法调用,就完全不需要使用标签。


中断或折叠多个语句(实际上是堆栈帧)的一种方法是抛出一个异常,但不建议这样做,因为运行时展开堆栈非常昂贵,并且可能导致非常严重的难以调试未定义行为(请记住这一点)。

否则,按照我的建议,重写代码,使其能够以优雅的方式脱离循环。如果您不能以任何其他方式更改此代码,那么您将不得不导致异常…


除了Java支持标记断言之外,如果达到结束条件,还可以在C++中提前退出AO吗?这是一个与其他相关解决方案类似的问题。


简单的解决方案是将整个搜索过程放入一个方法中,并且在得到答案后立即执行return

但是,您的示例代码的抽象形式还存在一些其他可能的问题。例如,是否有一种方法可以"索引"某些内容(例如,使用Map个实例),以便不必使用暴力循环?


抛出异常并在循环之外捕获它?使用"有害"的东西?

当计算机科学把自己描绘成一个角落时,有点滑稽;—)