Руководство по итератору в Java

Руководство по итератору в Java

1. Вступление

Iterator - это один из многих способов обхода коллекции, и, как каждый вариант, он имеет свои плюсы и минусы.

Впервые он был представлен в Java 1.2 как заменаEnumerations и:

В этом руководстве мы рассмотрим простой интерфейсIterator, чтобы узнать, как мы можем использовать его различные методы.

Мы также проверим более надежное расширениеListIterator, которое добавляет некоторые интересные функции.

2. ИнтерфейсIterator

Для начала нам нужно получитьIterator изCollection; это делается путем вызова методаiterator().

Для простоты мы получим экземплярIterator из списка:

List items = ...
Iterator iter = items.iterator();

ИнтерфейсIterator имеет три основных метода:

2.1. hasNext()с

МетодhasNext() можно использовать для проверки, есть ли хотя бы один элемент, который нужно перебрать.

Он предназначен для использования в качестве условия в циклахwhile:

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

2.2. next()с

Методnext() можно использовать для перехода к следующему элементу и его получения:

String next = iter.next();

Перед попыткой вызоваnext() рекомендуется использоватьhasNext().

Iterators дляCollections не гарантирует итерацию в каком-либо конкретном порядкеunless particular implementation provides it.

2.3. remove()с

Наконец, если мы хотимremove the current element from the collection,, мы можем использоватьremove:

iter.remove();

Это безопасный способ удаления элементов во время итерации по коллекции без рискаConcurrentModificationException.

2.4. ПолныйIterator Пример

Теперь мы можем объединить их все и посмотреть, как мы используем три метода вместе для фильтрации коллекций:

while (iter.hasNext()) {
    String next = iter.next();
    System.out.println(next);

    if( "TWO".equals(next)) {
        iter.remove();
    }
}

Вот как мы обычно используемIterator,, мы заранее проверяем, есть ли другой элемент, мы извлекаем его, а затем выполняем с ним какое-то действие.

2.5. Итерация с помощью лямбда-выражений

Как мы видели в предыдущих примерах, очень многословно использоватьIterator, когда мы просто хотим пройтись по всем элементам и что-то с ними сделать.

Начиная с Java 8, у нас есть методforEachRemaining, который позволяет использовать лямбды для обработки оставшихся элементов:

iter.forEachRemaining(System.out::println);

3. ИнтерфейсListIterator

ListIterator - это расширение, которое добавляет новые функции для перебора списков:

ListIterator listIterator = items.listIterator(items.size());

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

3.1. hasPrevious() иprevious()

ListIterator может использоваться для обратного обхода, поэтому он предоставляет эквивалентыhasNext() иnext():

while(listIterator.hasPrevious()) {
    String previous = listIterator.previous();
}

3.2. nextIndex() иpreviousIndex()

Кроме того, мы можем просматривать индексы, а не фактические элементы:

String nextWithIndex = items.get(listIterator.nextIndex());
String previousWithIndex = items.get(listIterator.previousIndex());

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

3.3. add()с

Методadd, который, как следует из названия, позволяет нам добавить элементbefore the item that would be returned by next() and after the one returned by previous():

listIterator.add("FOUR");

3.4. set()с

Последний метод, о котором стоит упомянуть, -set(),, который позволяет нам заменить элемент, который был возвращен при вызове, наnext() илиprevious():

String next = listIterator.next();
if( "ONE".equals(next)) {
    listIterator.set("SWAPPED");
}

Важно отметить, чтоthis can only be executed if no prior calls to add() or remove() were made.

3.5. ПолныйListIterator Пример

Теперь мы можем объединить их все, чтобы сделать полный пример:

ListIterator listIterator = items.listIterator();
while(listIterator.hasNext()) {
    String nextWithIndex = items.get(listIterator.nextIndex());
    String next = listIterator.next();
    if("REPLACE ME".equals(next)) {
        listIterator.set("REPLACED");
    }
}
listIterator.add("NEW");
while(listIterator.hasPrevious()) {
    String previousWithIndex
     = items.get(listIterator.previousIndex());
    String previous = listIterator.previous();
    System.out.println(previous);
}

В этом примере мы начинаем с полученияListIterator изList, затем мы можем получить следующий элемент либо по индексу -which doesn’t increase the iterator’s internal current element - либо путем вызоваnext.

Затем мы можем заменить конкретный элемент наset и вставить новый сadd.

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

4. Заключение

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

Наконец, как всегда доступен полный исходный кодover at GitHub.