Вопрос:

Разница между перемещением итератора вперед с помощью оператора for и оператора while

java iterator for-loop while-loop

35938 просмотра

5 ответа

1203 Репутация автора

Когда я использую Iterator of Object, я использую цикл while (как написано в каждой книге, изучающей Java, как Thinking in Java Брюса Эккеля):

Iterator it=...

while(it.hasNext()){
    //...
}

но иногда я видел, что вместо этого кто-то использует цикл for :

Iterator it=...
for (Iterator it=...; it.hasNext();){
    //...
}

Я не понимаю этот выбор:

  • Я использую цикл for, когда у меня есть коллекция с порядковой последовательностью (в виде массива) или со специальным правилом для шага (обычно объявляется как простое приращение counter++).
  • Я использую цикл while, когда цикл заканчивается с помощью «У меня нет ограничений», а только логическое условие для выхода.

Это вопрос стилевого кодирования без какой-либо другой причины или существует какая-то другая логика (например, производительность), которую я не знаю?

Спасибо за каждый отзыв

Автор: alepuzio Источник Размещён: 05.02.2009 11:49

Ответы (5)


9 плюса

16764 Репутация автора

Это просто стиль, и, как и вы, я предпочитаю цикл for при использовании чего-либо с индексом. Если вы используете Java 5, вы, конечно, должны в любом случае использовать цикл foreach над коллекцией:

Collection<String> someCollection = someCollectionOfString();
for (String element : someCollection) {
....
}
Автор: tddmonkey Размещён: 05.02.2009 11:54

32 плюса

9122 Репутация автора

Решение

Правильный синтаксис для цикла for:

for (Iterator it = ...; it.hasNext(); ){
    //...
}

(Предыдущее объявление в вашем коде является излишним, равно как и лишняя точка с запятой в заголовке цикла for.)

Используете ли вы этот синтаксис или whileцикл - дело вкуса, и то, и другое переводится в точности одинаково. Общий синтаксис цикла for:

for (<init stmt>; <loop cond>; <iterate stmt>) { <body>; }

что эквивалентно:

<init stmt>;
while (<loop cond>) { <body>; <iterate stmt>; }

Изменить: На самом деле, две вышеупомянутые формы не полностью эквивалентны, если (как в вопросе) переменная объявляется с оператором init. В этом случае будет разница в области действия переменной итератора. В случае цикла for область действия ограничена самим циклом, в случае цикла while, однако область действия распространяется до конца включающего блока (что не вызывает большого удивления, поскольку объявление находится вне цикла).

Также, как отмечали другие, в более новых версиях Java есть сокращенная запись цикла for:

for (Iterator<Foo> it = myIterable.iterator(); it.hasNext(); ) {
    Foo foo = it.next();
    //...
}

можно записать как:

for (Foo foo : myIterable) {
    //...
}

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

Автор: David Hanak Размещён: 05.02.2009 11:54

2 плюса

88104 Репутация автора

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

Одно конкретное конкретное преимущество более длинной конструкции цикла for заключается в том, что у вас есть ссылка на итератор, и поэтому вы можете вызывать другие методы next(). В частности, hasNext()часто может быть полезно вызвать - представьте, если вы хотите распечатать список строк через запятую:

StringBuilder sb = new StringBuilder();
for (Iterator it=...; it.hasNext();){
   sb.append(it.next());
   if (it.hasNext())
      sb.append(", ");
}

Подобный случай можно выделить только в том случае, если вы используете более подробный цикл for.

Автор: Andrzej Doyle Размещён: 05.02.2009 11:56

4 плюса

44937 Репутация автора

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

На самом деле, есть и третий способ. Например, вместо того, чтобы писать

for (Iterator<SomeObject> it = foo.iterator(); it.hasNext();) {
  SomeObject so = foo.next();
}

Вы можете чаще всего писать

for (SomeObject so: foo) {...}

Эти два равны одному и тому же ...

Автор: Henrik Paul Размещён: 05.02.2009 11:57

9 плюса

113595 Репутация автора

Целью объявления цикла Iteratorfor является минимизация области видимости ваших переменных , что является хорошей практикой.

Когда вы объявляете Iteratorвнешнюю часть цикла, ссылка остается действительной / активной после завершения цикла. В 99,99% случаев вам не нужно продолжать использовать Iteratorпосле завершения цикла, поэтому такой стиль может привести к таким ошибкам:

//iterate over first collection
Iterator it1 = collection1.iterator();
while(it1.hasNext()) {
   //blah blah
}

//iterate over second collection
Iterator it2 = collection2.iterator();
while(it1.hasNext()) {
   //oops copy and paste error! it1 has no more elements at this point
}
Автор: matt b Размещён: 05.02.2009 02:40
Вопросы из категории :
32x32