Ответ 1
Я предпочитаю цикл for, потому что он также задает область итератора только для цикла for.
Я часто вижу код вроде:
Iterator i = list.iterator();
while(i.hasNext()) {
...
}
но я пишу, что (когда Java 1.5 недоступен или для каждого не может использоваться):
for(Iterator i = list.iterator(); i.hasNext(); ) {
...
}
потому что
i
в меньшей областиi
используется вне
в то время как? Где объявлено i
?)Я думаю, что код должен быть как можно более понятным, так что мне нужно сделать сложный код, чтобы делать сложные вещи. Как вы думаете? Что лучше?
От: http://jamesjava.blogspot.com/2006/04/iterating.html
Я предпочитаю цикл for, потому что он также задает область итератора только для цикла for.
Почему бы не использовать конструкцию for-each? (Я не использовал Java некоторое время, но это существует в С#, и я уверен, что 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 и foreach конструкций:
while
- Используйте это, если вы выполняете итерацию, и решающий фактор для цикла или нет основан только на условии. В этой конструкции цикла сохранение индекса является лишь вторичной проблемой; все должно основываться на условии
for
- Используйте это, если вы зацикливаете, и ваша главная проблема - это индекс массива/коллекции/списка. Полезнее использовать for для, если вы, скорее всего, пройдете все элементы и в определенном порядке (например, перейдя через отсортированный список, например).
foreach
- Используйте это, если вам просто нужно пройти свою коллекцию независимо от порядка.
Очевидно, что есть исключения из вышеизложенного, но что общее правило, которое я использую при принятии решения об использовании, которое. При этом я чаще использую foreach
.
Я думаю, что область является самой большой проблемой здесь, как вы указали.
В примере "while" итератор объявляется вне цикла, поэтому он будет продолжать существовать после завершения цикла. Это может вызвать проблемы, если этот же итератор снова используется в какой-то более поздний момент. E. g. вы можете забыть инициализировать его, прежде чем использовать его в другом цикле.
В примере "for" итератор объявляется внутри цикла, поэтому его область ограничена циклом. Если вы попытаетесь использовать его после цикла, вы получите ошибку компилятора.
если вы только собираетесь использовать итератор один раз и выбросить его, предпочтительна вторая форма; иначе вы должны использовать первую форму
IMHO, цикл для менее читабельен в этом сценарии, если вы посмотрите на этот код с точки зрения английского языка. Я работаю над кодом, в котором автор злоупотребляет циклом для, и это не очень хорошо. Сравните следующие:
for (; (currUserObjectIndex < _domainObjectReferences.Length) && (_domainObjectReferences[currUserObjectIndex].VisualIndex == index); ++currUserObjectIndex)
++currNumUserObjects;
vs
while (currUserObjectIndex < _domainObjectReferences.Length && _domainObjectReferences[currUserObjectIndex].VisualIndex == index)
{
++currNumUserObjects;
++currUserObjectIndex;
}
Я бы согласился, что цикл "for" более ясен и более уместен при повторении.
Цикл "while" подходит для опроса или где количество циклов, удовлетворяющих условию выхода, будет изменяться в зависимости от активности внутри цикла.
Не то, чтобы в этом случае это имело значение, но у компиляторов, виртуальных машин и процессора обычно есть специальные методы оптимизации, которые они используют под капотом, которые улучшат производительность петель (и в ближайшем будущем параллельны), в общем случае они не делайте это с циклом while (потому что его сложнее определить, как он на самом деле будет работать). Но в большинстве случаев четкость кода должна превзойти оптимизацию.
Используя цикл for, вы можете работать с одной переменной, поскольку она устанавливает область действия переменной для текущей работы только для цикла. Однако это невозможно в цикле while.
Например:
int i; for (i = 0; in1; я ++) что-то делать..
для (i = 0; я n2; я + = 2) что-то делать.
Итак, после 1-го цикла я = n1-1 в конце. Но при использовании второго цикла вы можете снова установить я на 0. Однако
int я = 0;
while (i меньше предела) {сделайте что-то..; я ++; }
Следовательно, я в конце устанавливается в limit-1. Таким образом, вы не можете использовать один и тот же я в другом цикле while.
Либо все нормально. Я сам использую for(), и я не знаю, есть ли проблемы с компиляцией. Я подозреваю, что они оба оптимизированы до почти той же самой вещи.
Хотя оба варианта действительно прекрасны, я использую первый пример, потому что его легче читать.
В каждой строке происходит меньше операций с циклом while(), что делает код более легким для кого-то нового для кода, чтобы понять, что происходит.
Этот тип конструкции также позволяет мне группировать инициализации в общем месте (вверху метода), что также упрощает комментирование для меня и концептуализацию для кого-то, читающего его в первый раз.
Я согласен, что цикл for должен использоваться по возможности, но иногда есть более сложная логика, которая управляет итератором в теле цикла. В этом случае вам нужно идти вместе.
Я был для цикла for для ясности. Хотя я использую цикл while, когда сталкиваюсь с каким-то неопределенным условием.
Оба хороши, но помните, что иногда доступ к Iterator напрямую полезен (например, если вы удаляете элементы, которые соответствуют определенному условию), вы получите исключение ConcurrentModificationException, если вы делаете collection.remove(o) внутри a for ( T o: collection).
Я предпочитаю писать синтаксис for (blah: blah) [foreach] почти все время, потому что мне кажется более понятным для меня. Понятие итераторов вообще не имеет параллелей вне программирования