2009-02-15 4 views
29

У меня есть четыре петли foreach, которые проходят через коллекции и на основе состояния делают что-то. Вот код, который я сейчас пишу:Как разбить несколько циклов 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. Или если есть какой-либо другой способ рефакторинга этого кода, чтобы сделать его более читабельным и поддерживаемым. Благодарю.

+0

Btw, это * для * нет * foreach *. –

+3

Нет, for (Object o: os) фактически известен как цикл foreach или iterator. – Esko

+0

Оригинальная версия имела «foreach» в самом коде. Спасибо за редактирование. – royalGhost

ответ

78

Используйте ярлык на самой внешней петле и включите эту метку в инструкцию 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 
+4

Это правильный ответ на мой вопрос. Но, я реорганизовал, как и другие люди, предложил и перевел логику на небольшую функцию и использовал «возврат». – royalGhost

+0

Использовать ярлык Функции, только если у вас нет другого решения. Это не хорошая практика. – lucasddaniel

0

Выбросить исключение и поймать его за пределами петель? Использовать то, что считается «вредным»?

Это немного смешно, когда информатику рисует себя в угол ;-)

+3

«Информатика» не «рисует себя в угол». Но иногда программисты делают ранний выбор или предположения, которые ограничивают их варианты позже. –

+2

Думаю, я смешной. Результаты могут отличаться. – dwc

+0

Результаты могут отличаться. ROFL. –

1

Один из способов сломать, или свернуть несколько заявлений (на самом деле стек кадров), чтобы бросить исключение, но это не рекомендуется, потому что это на самом деле дорогое время для разворачивания стека, и это может привести к действительно неприятному отлаживанию неопределенного поведения (помните об этом).

В противном случае, что я рекомендую, перепишите этот код, чтобы он мог изгонять из цикла изящным образом. Если вы не можете изменить этот код каким-либо другим способом, то тогда вам придется привести к исключениям ...

+0

Java поддерживает метки, но их можно использовать только с операторами break и continue. –

19

Извлеките все циклы в функцию и используйте возврат.

+0

Код, как показано, не очень приятный: рефакторинг вдоль этих линий будет намного лучше. – Fortyrunner

+2

это предпочтительный способ использования ярлыков разрыва, если только вы не знаете, что лучше использовать разрыв. – Chii

+0

Представление границы метода в произвольном месте является «предпочтительным способом»? –

6

Вы можете использовать меченый заявление перерыв. Такой перерыв заканчивается внешней инструкции

См The break Statement

0

Прямое решение поставить весь процесс поиска в методе и return, как только у вас есть ответ.

Однако абстрактная форма вашего образца кода оставляет некоторые другие возможности. Например, существует ли способ «проиндексировать» часть содержимого (например, с использованием Map экземпляров), так что вам не нужно использовать петли грубой силы?

2

См. Branching Statements Java Tutorial для простейшего способа, используя ярлык. Вы можете пометить любые или все циклы for, а затем использовать break или continue в сочетании с этими ярлыками.

Альтернативой использованию этикеток является использование вместо return. Просто переформатируйте свой код в вызове метода, чтобы обойти необходимость использования меток вообще.

2

Ваш пример довольно общий, поэтому трудно сказать, что происходит, но я получаю такой сильный запах кода из кода, который вы указали, что я вынужден думать, что должен быть другой способ сделать это полностью , скорее всего, путем реорганизации фактической структуры данных в нечто более значимое.

Какой список objects есть? Что еще (скорее всего, важно) данных, которые он содержит? Если это не слишком много хлопот, я был бы признателен, если бы вы предоставили более подходящий код, поскольку рефакторинг во мне становится все головокружительным, просто видя эту кучу циклов.