Когда использовать для (int i = 0;;) / для каждого / итератора для прохождения списка - PullRequest
1 голос
/ 08 августа 2011

Является ли предпочтительным использование традиционного цикла for, цикла for-each или итератора для прохождения списка?

1) for(MyClass mc : al){ // do something on mc }
or

2) iter = arrayList.iterator();
while(iter.hasNext()){MyClass mc = iter.Next()}

Ответы [ 9 ]

4 голосов
/ 08 августа 2011

Для большинства итераций вы должны использовать обычный цикл:

for (Object o : list) { /* */ }

Он гораздо более читабелен, цель ясна, а потенциальные ошибки сведены к минимуму.

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

4 голосов
/ 08 августа 2011

Вы можете использовать итераторы, чтобы избежать ConcurrentModificationExceptions.

iter = arrayList.iterator();
while(iter.hasNext()) {
  MyClass mc = iter.next();

  if(shouldItBeRemoved(mc)) {
    iter.remove(); // Will not throw ConcurrentModificationException
    // arrayList.remove(mc); // Will throw CME
  }
}

Тем не менее я считаю цикл for-each более читабельным, поэтому используйте его всякий раз, когда вы не изменяете список в цикле.

2 голосов
/ 08 августа 2011

Я предпочитаю

1) Если мне нужно продвигаться по списку без каких-либо изменений в объекте List, для читаемого и чистого кода я буду использовать:

for(MyClass mc : list){
    /* code without modification to list */
}

2) Если мне нужно изменить объект List, я без сомнения буду использовать:

iter = list.iterator();
while(iter.hasNext()) {
    MyClass mc = iter.next()
    /* code without modification to list */
    /* code with modification to list */
}

Дополнительная информация:

Итератор будет полезен, если вам нужно создать служебный методкоторые могут проходить через несколько типов коллекций (например, ArrayList, LinkedList, HashSet, TreeSet, LinkedHashSet)

public class Example {
  public static void iterateAndDoSomething(Iterator<MyClass> iter) {
    while(iter.hasNext()) {
        MyClass mc = iter.next();
        /* code without modification to list */
        /* code with modification to list */
    }
  }

  public static void main(String[] args) {
    ArrayList<MyClass> als = new ArrayList<MyClass>();
    TreeSet<MyClass> tss = new TreeSet<MyClass>();
    iterateAndDoSomething(als.iterator());
    iterateAndDoSomething(tss.iterator());
  }
}
1 голос
/ 08 августа 2011

Традиционные циклы (на основе индекса) полезны, когда вам нужен индекс для манипулирования массивом.

Если вас не интересуют индексы и вас интересует только получение значения из массива, цикл for..each подходит лучше всего.

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

1 голос
/ 08 августа 2011

Я использую for (i=0;, если мне нужен индекс во время цикла, или iterator(), если это единственно возможное, или мне нужно remove() элементов (одновременно).Для всех остальных случаев я использую сокращенный цикл for for(MyClass mc : al) из-за его читабельности.

1 голос
/ 08 августа 2011

В некоторых классах нет метода iterator() (например, NodeList), тогда вы должны использовать # 1.Кроме этого, это вопрос предпочтений, я думаю.

0 голосов
/ 12 сентября 2012

Я читал, что итераторы очень полезны в Swing, особенно если вы перебираете коллекцию в методе paintComponent(Graphics g).

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

Поведение итератора не определено, если основной коллекция модифицируется во время выполнения итерации любым способом кроме вызова этого метода. Это означает, что если вы изменяете одну и ту же коллекцию одновременно, то поведение метода remove не определяется. НО метод удаления хорошо работает ДАЖЕ ЕСЛИ вы проходите через одну и ту же коллекцию одновременно при вызове iterator.remove () !!! Я использовал это в моем графическом интерфейсе.

По моему опыту необходимо использовать итератор в методе paintComponent вместо цикла for или for-each!

0 голосов
/ 08 августа 2011

Цикл for-each-недоступен в Java 1.4, поэтому его можно устранить, если вам требуется поддержка Java <1.5. </p>

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

0 голосов
/ 08 августа 2011

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

При наличии обоих у вас есть гибкость в выборе того, что вы хотели бы выбрать.

...