Итерировать с помощью цикла for или цикла while?
Вопрос
Я часто вижу такой код:
Iterator i = list.iterator();
while(i.hasNext()) {
...
}
но я пишу это (когда Java 1.5 недоступна или для каждого из них невозможно использовать) как:
for(Iterator i = list.iterator(); i.hasNext(); ) {
...
}
потому что
- Это короче
- Он держит
i
в меньшем объеме - Это снижает вероятность путаницы.(Является
i
Используется вне времени?Гдеi
заявлено?)
Я считаю, что код должен быть максимально простым для понимания, чтобы мне приходилось создавать сложный код только для выполнения сложных задач.Что вы думаете?Как лучше?
Решение
Я предпочитаю цикл for, потому что он также устанавливает область действия итератора только для цикла for.
Другие советы
Существуют подходящие варианты использования конструкций while, for и foreach:
while
- Используйте это, если вы выполняете итерацию, и решающий фактор, зацикливаться или нет, основан просто на условии.В этой конструкции цикла сохранение индекса является лишь второстепенной задачей;все должно быть основано на состоянииfor
- Используйте это, если вы выполняете цикл и вашей основной задачей является индекс массива/коллекции/списка.Полезнее использовать for, если вы, скорее всего, пройдете через все элементы в любом случае и в определенном порядке (например, проходя назад по отсортированному списку).foreach
- Используйте это, если вам просто нужно просмотреть свою коллекцию независимо от порядка.
Очевидно, что из вышеперечисленного есть исключения, но это общее правило, которое я использую, решая, какое из них использовать.При этом я склонен использовать foreach
чаще.
Почему бы не использовать конструкцию for-each?(Я давно не использовал Java, но это существует в C#, и я почти уверен, что в Java 1.5 это тоже есть):
List<String> names = new ArrayList<String>();
names.add("a");
names.add("b");
names.add("c");
for (String name : names)
System.out.println(name.charAt(0));
Я думаю, что масштаб является здесь самой большой проблемой, как вы отметили.
В примере while итератор объявлен вне цикла, поэтому он продолжит существовать после завершения цикла.Это может вызвать проблемы, если тот же итератор будет использоваться снова в какой-то момент позже.Э.г.вы можете забыть инициализировать его перед использованием в другом цикле.
В примере for итератор объявляется внутри цикла, поэтому его область действия ограничена циклом.Если вы попытаетесь использовать его после цикла, вы получите ошибку компилятора.
если вы собираетесь использовать итератор только один раз и выбросить его, предпочтительна вторая форма;в противном случае вы должны использовать первую форму
ИМХО, для В этом сценарии цикл менее читабелен, если посмотреть на этот код с точки зрения английского языка.Я работаю над кодом, в котором автор злоупотребляет для петля, и это некрасиво.Сравните следующее:
for (; (currUserObjectIndex < _domainObjectReferences.Length) && (_domainObjectReferences[currUserObjectIndex].VisualIndex == index); ++currUserObjectIndex)
++currNumUserObjects;
против
while (currUserObjectIndex < _domainObjectReferences.Length && _domainObjectReferences[currUserObjectIndex].VisualIndex == index)
{
++currNumUserObjects;
++currUserObjectIndex;
}
Я согласен, что цикл for более понятен и уместен при итерации.
Цикл while подходит для опроса или для случаев, когда количество циклов, отвечающих условию выхода, будет меняться в зависимости от активности внутри цикла.
Не то чтобы это, вероятно, имело значение в данном случае, но компиляторы, виртуальные машины и процессоры обычно имеют специальные методы оптимизации, которые они используют под капотом, которые улучшат производительность циклов (и в ближайшем будущем параллельную работу), как правило, они не делают этого с while (потому что сложнее определить, как он будет работать на самом деле).Но в большинстве случаев ясность кода должна превосходить оптимизацию.
Используя цикл for, вы можете работать с одной переменной, поскольку она устанавливает область действия переменной только для текущего рабочего цикла for.Однако это невозможно в цикле while.Например:
интервал я;для (я = 0;in1;i++) сделай что-нибудь..
for(i=0;i n2;i+=2) сделайте что-нибудь.
Итак, после 1-го цикла i=n1-1 в конце.Но при использовании второго цикла вы можете снова установить i на 0. Однако
интервал я = 0;
while(i меньше лимита) {сделай что-нибудь ..;я++;}
Следовательно, в конце для меня установлено значение limit-1.Таким образом, вы не можете использовать тот же i в другом цикле while.
Либо это нормально.Я сам использую for() и не знаю, есть ли проблемы с компиляцией.Я подозреваю, что они оба оптимизированы примерно до одного и того же.
Я согласен, что цикл for следует использовать везде, где это возможно, но иногда существует более сложная логика, которая управляет итератором в теле цикла.В этом случае вам придется использовать while.
Я был циклом for для ясности.Пока я использую пока цикл когда сталкиваешься с каким-то недетерминированным условием.
Оба варианта хороши, но помните, что иногда полезен прямой доступ к итератору (например, если вы удаляете элементы, соответствующие определенному условию, — вы получите исключение ConcurrentModificationException, если вы выполните Collection.remove(o) внутри for(T o :коллекция) цикл).
Я предпочитаю писать for(blah:бла) Синтаксис [foreach] почти всегда, потому что мне он кажется более естественным для чтения.Концепция итераторов в целом не имеет аналогов за пределами программирования.
Научные круги склонны отдавать предпочтение циклу while, поскольку он упрощает рассуждения о программах.Я предпочитаю структуры цикла for или foreach, поскольку они облегчают чтение кода.
Хотя оба варианта действительно хороши, я предпочитаю использовать первый пример, потому что его легче читать.
В каждой строке цикла while() выполняется меньше операций, что облегчает понимание кода тем, кто не знаком с кодом.
Этот тип конструкции также позволяет мне группировать инициализации в общем месте (вверху метода), что также упрощает комментирование для меня и концептуализацию для тех, кто читает это впервые.