33

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

这是我现在正在编写的代码:

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,因此我无法更改该部分的任何内容。我想问问 Stack Overflow 社区是否有更好的方法来打破所有四个 foreach 循环。或者是否有任何其他方法可以重构此代码以使其更具可读性和可维护性。

4

9 回答 9

81

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

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
于 2009-02-15T21:06:39.163 回答
20

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

于 2009-02-15T21:06:20.083 回答
6

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

请参阅break 语句

于 2009-02-15T21:09:13.557 回答
2

有关使用标签的最简单方法,请参阅分支语句 Java 教程。您可以标记任何或所有 for 循环,然后使用这些标签breakcontinue与这些标签结合使用。

使用标签的替代方法是使用return。只需将您的代码重构为方法调用即可完全绕过使用标签的需要。

于 2009-02-15T21:31:35.157 回答
2

您的示例相当通用,因此很难说出发生了什么,但是我从您提供的代码中得到了如此强烈的代码气味,以至于我不得不认为必须有另一种方法来完全做这件事,很可能是通过将实际的数据结构重构为更有意义的东西。

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

于 2009-02-16T06:55:09.170 回答
1

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

否则,我建议重写该代码,以便能够以优雅的方式跳出循环。如果您不能以任何其他方式更改此代码,那么您将不得不导致异常...

于 2009-02-15T21:05:31.320 回答
0

抛出异常并在循环之外捕获它?使用“被认为有害”的东西?

当计算机科学把自己画到一个角落时,这有点好笑;-)

于 2009-02-15T21:04:16.283 回答
0

直接的解决方案是将整个搜索过程放在一个方法中,return一旦你有答案。

但是,您的示例代码的抽象形式留下了一些其他可能性。例如,有没有办法“索引”一些内容(例如使用Map实例),这样您就不必使用暴力循环?

于 2009-02-15T21:10:18.530 回答
0

除了 Java 支持标记中断这一事实外,另请参阅如果达到结束条件,是否可以在 C++ 中退出 for before time?这是与其他一些相关解决方案类似的问题。

于 2009-02-15T21:20:41.267 回答