Подтвердить что ты не робот

Зачем нам нужно использовать итератор на ArrayList в Java?

Я читал ответ, упомянутый на вопрос "Нужно ли нам когда-либо использовать Итераторы на ArrayList?".

В ответе пользователь сказал что-то вроде этого: "Большой вариант использования итераторов с ArrayLists - это когда вы хотите удалить элементы во время итерации".

Это может быть достигнуто даже при использовании метода удаления ArrayList в Java. Мой вопрос: зачем нужен итератор в ArrayList?

Рассмотрим код:

import java.util.*;
public class ocajp66 {
    public static void main(String[] args) {
        ArrayList a = new ArrayList();
        for (int i = 0; i < 10; i++) {
            a.add(i);
        }
        System.out.printf("BEFORE ITERATOR\n");
        for (int i = 0; i < a.size(); i++) {
            System.out.printf("I:%d\n", a.get(i));
        }
        System.out.printf("AFTER ITERATOR\n");
        Iterator i = a.iterator();
        while (i.hasNext()) {
            System.out.printf("I:%d\n", i.next());
        }
    }
}

Может ли кто-нибудь объяснить значение итератора? Было бы замечательно, если бы вы могли объяснить мне код.

4b9b3361

Ответ 1

Как вы сказали, iterator используется, когда вы хотите удалить материал, пока вы перебираете содержимое массива. Если вы не используете итератор, но просто имеете цикл for, и внутри него используется метод remove, вы получите исключения, потому что содержимое массива изменяется, пока вы перебираете. например: вы можете подумать, что размер массива равен 10 в начале цикла for, но это будет не так, как только вы удалите материал. Поэтому, когда вы достигнете последних циклов, вероятно, будет IndexOutofBoundsException и т.д.

Ответ 2

Понятно, что API ArrayList -like может работать без метода iterator(). Тем не менее, ArrayList является Collection, а метод iterator() определен в интерфейсе Collection... поэтому ArrayList должен его реализовать.

Точка об удалении из ArrayList заключается в том, что при выполнении индексирования требуется некоторое размышление:

    for (int i = 0; 
         i < a.size(); // Hoist this at your peril
         i++) {
        if (a.get(i) == something) {
            a.remove(i);
            i--;  // Leave this out at your peril
        }
    }

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

Третья причина, по которой iterator - хорошая вещь на ArrayList, заключается в том, что она позволяет использовать синтаксис Java 5 for (type var : iterable) ....

Суть в том, что вам не нужно использовать итераторы в экземплярах ArrayList. Если вы этого не хотите, не делайте этого.

Ответ 3

Это пример того, как можно получить нужные результаты несколькими способами. Такая избыточность не уникальна для Java.

  • for (int я = 0; я < myArray.length; я ++) {...}

Этот синтаксис был введен в ранних версиях Java. Он выполняет итерацию по обычному массиву Java в цикле {}. Это, как правило, безопасно, поскольку массивы Java являются фиксированной длиной, поэтому исключение "Index Out of Bounds" невозможно.

  • for (int я = 0; я < myArrayList.size(); я ++ {...}

Этот синтаксис отражает более позднюю версию Java после введения API коллекций, в котором был введен ArrayList. Классы, реализующие интерфейс Collection, как уже упоминалось выше, должны реализовывать Iterator, но вам не нужно его использовать. Это для цикла {} не существует, но опасность здесь в том, что ArrayLists не являются фиксированным размером. Если он должен сжиматься в теле цикла for, и может возникнуть исключение.

  • для (MyArrayType t: myArrayList) {}

Этот синтаксис также был выпущен в более позднем выпуске Java. Он называется усиленным циклом. Любой класс коллекции, предоставляющий Iterator, реализуя интерфейс Iterable, может воспользоваться этим синтаксисом. Это позволяет выполнять итерацию элементов в коллекции без явного создания экземпляра Iterator. Излюбленным способом использования этого в приложении JavaFX является цикл через набор элементов управления, чтобы установить свойство в значение, например. на reset содержимое группы TextFields:

for (TextField tf : new TextField[] { txtf1, txtf2, txtf3, txtfa, txtfb, txtfc}) {
    tf.setText("");
}
  • while (myCollectionIterator.hasNext()) {}

Вы всегда можете явно создать экземпляр Iterator. Это безопасно использовать при изменении размера коллекции (из собственных методов Collection). Правильно сказать, что Iterator более тесно связан с интерфейсом Iterable, чем с характеристикой основного языка Java. Но вы все равно можете использовать его в качестве языковой функции (в расширенном для цикла) благодаря более поздним версиям Java.

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

Ответ 4

В: Зачем нужен итератор в ArrayList?

Мы не делаем - так же, как вы показали в своем коде, вы можете выполнять итерации и выполнять основные операции в ArrayList без итератора. Но это приятно иметь функцию.

Q: Кто-нибудь может объяснить значение итератора?

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

Итераторы, возвращаемые этим классом итератором и listIterator методы fail-fast: если список структурно модифицирован в любом время после создания итератора, любым способом, за исключением итератор самостоятельно удаляет или добавляет методы, итератор будет бросать ConcurrentModificationException. Таким образом, перед лицом параллельных модификации, итератор выходит из строя быстро и чисто, а не рискуя произвольным, недетерминированным поведением в неопределенное время в будущем.

Вы искали код, вы можете увидеть здесь реализацию итератора ArrayList: ArrayList.java.

Ответ 5

По вашему вопросу, если мы используем метод list.remove() вместо iterator.remove(), тогда будет выбрано IndexOutOfBoundsException.

list.remove() безопасен в использовании, если вы помещаете оператор break после удаления определенного объекта/индекса, чтобы он был удален из цикла без исключения (например, IndexOutOfBoundsException)

После кода итератора все еще можно бросить ConcurrentModificationException, если мы используем итератор EVEN в синхронизированной среде.

List<String> empNames = new ArrayList<String>();
        synchronized (empNames) {
            Iterator<String> iterator = empNames.iterator();
            while (iterator.hasNext()) {
                iterator.next();
                empNames.add("Another Name"); // throws
                // ConcurrentModificationException
            }
        }