【问题标题】:How do I break multiple foreach loops? [duplicate]如何打破多个 foreach 循环? [复制]
【发布时间】:2010-10-07 18:50:56
【问题描述】:

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

【问题讨论】:

  • 顺便说一句,它是 for 而不是 foreach
  • 不,for(Object o: os) 实际上被称为 foreach 或迭代器循环。
  • 原始版本的代码中包含“foreach”。感谢编辑。

标签: java refactoring foreach


【解决方案1】:

在最外面的循环上使用一个标签,当你想跳出所有循环时,在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

【讨论】:

  • 这是我问题的正确答案。但是,我像其他人建议的那样进行了重构,并将逻辑移到了一个小函数中并使用了“return”。
  • 只有在没有其他解决方案时才使用标签函数。不是一个好习惯。
【解决方案2】:

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

【讨论】:

  • 显示的代码不太好:按照这些思路重构会好得多。
  • 这是使用中断标签的首选方式,除非您知道使用中断更清晰。
  • 在任意位置引入方法边界是“首选方式”?
  • 使用标签更好
【解决方案3】:

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

The break Statement

【讨论】:

    【解决方案4】:

    请参阅Branching Statements Java Tutorial,了解使用标签的最简单方法。您可以标记任何或所有 for 循环,然后将 breakcontinue 与这些标签结合使用。

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

        • Java 确实支持标签,但它们只能与 break 和 continue 语句一起使用。
        【解决方案7】:

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

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

        【讨论】:

        • “计算机科学”不会“把自己画到角落里”。但有时程序员会做出早期的选择或假设,这会限制他们以后的选择。
        • 我觉得我很有趣。结果可能会有所不同。
        【解决方案8】:

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

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

        【讨论】:

          【解决方案9】:

          除了 Java 支持带标签的 break 之外,另请参阅 Is it possible to exit a for before time in C++, if an ending condition is reached?,这是与其他一些相关解决方案类似的问题。

          【讨论】:

            猜你喜欢
            • 2018-02-08
            • 2011-12-08
            • 1970-01-01
            • 2010-09-16
            • 1970-01-01
            • 1970-01-01
            • 2019-02-14
            • 2019-01-15
            相关资源
            最近更新 更多