Ръководство за Iterator в Java

1. Въведение

Един Итераторът е един от многото начини да преминават колекция, и като всеки вариант, тя има своите плюсове и минуси.

За първи път беше представен в Java 1.2 като заместител на изброяванията и:

  • въведе подобрени имена на методи
  • направи възможно премахването на елементи от колекция, която итерираме
  • не гарантира итерационна поръчка

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

Ще проверим и по-стабилното разширение ListIterator, което добавя някои интересни функционалности.

2. Интерфейсът на Итератора

За начало трябва да получим итератор от колекция ; това става чрез извикване на метода iterator () .

За простота ще получим екземпляр на Iterator от списък:

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

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

2.1. hasNext ()

Методът hasNext () може да се използва за проверка дали е останал поне един елемент за итерация.

Той е проектиран да се използва като условие в циклите while :

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

2.2. следващия()

Методът next () може да се използва за преминаване през следващия елемент и получаването му:

String next = iter.next();

Добра практика е да използвате hasNext (), преди да се опитате да извикате next () .

Итераторите за колекции не гарантират повторение в някакъв определен ред, освен ако конкретното изпълнение не го предоставя.

2.3. Премахване()

И накрая, ако искаме да премахнем текущия елемент от колекцията, можем да използваме премахването:

iter.remove();

Това е безопасен начин за премахване на елементи по време на итерация върху колекция без риск от ConcurrentModificationException.

2.4. Пример за пълен итератор

Сега можем да ги комбинираме и да разгледаме как използваме трите метода заедно за филтриране на колекции:

while (iter.hasNext()) { String next = iter.next(); System.out.println(next); if( "TWO".equals(next)) { iter.remove(); } }

По този начин често използваме итератор, проверяваме предварително дали има друг елемент, извличаме го и след това извършваме някакво действие върху него.

2.5. Итерация с ламбда изрази

Както видяхме в предишните примери, много многословно е да използваме итератор, когато просто искаме да прегледаме всички елементи и да направим нещо с тях.

От Java 8 имаме метода forEachRemaining , който позволява използването на ламбда за обработка на останалите елементи:

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

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

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

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

Забележете как можем да осигурим начална позиция, която в този случай е краят на Списъка.

3.1. hasPrevious () и предишен ()

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 , който, както подсказва името, ни позволява да добавим елемент преди елемента, който ще бъде върнат от next () и след този, върнат от предишен ():

listIterator.add("FOUR");

3.4. комплект()

Последният метод, който си струва да се спомене, е set (), който ни позволява да заменим елемента, който е върнат при извикването към next () или previous () :

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

Важно е да се отбележи, че това може да бъде изпълнено само ако не са били направени предишни повиквания за добавяне () или премахване () .

3.5. Пример за пълен списък на Итератор

Вече можем да ги комбинираме, за да направим пълен пример:

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 от списъка , след което можем да получим следващия елемент или чрез индекс - което не увеличава вътрешния текущ елемент на итератора - или чрез извикване на next .

След това можем да заменим определен елемент с набор и да вмъкнем нов с добавяне.

След достигане на края на итерацията можем да се върнем назад, за да модифицираме допълнителни елементи или просто да ги отпечатаме отдолу нагоре.

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

Интерфейсът на Iterator ни позволява да модифицираме колекция, докато я обхождаме, което е по-трудно с прост оператор for / while. Това от своя страна ни дава добър модел, който можем да използваме в много методи, който изисква само обработка на колекции, като същевременно се поддържа добро сцепление и ниско свързване.

И накрая, както винаги пълният изходен код е достъпен в GitHub.