„Здрасти, Амиго!“

„Здравей, Ели!“

„Днес искам да ви разкажа за итераторите.“

"Итераторите са изобретени практически по същото време като колекциите. Основната цел на колекциите е да съхраняват елементи, а основната цел на итератора е да извлича тези елементи един по един."

"Какво е толкова трудно в получаването на набор от елементи?"

„Първо, елементите в някои колекции, като Set, нямат установен ред и/or редът се променя постоянно.“

„Второ, някои структури от данни могат да съхраняват обекти по много сложен начин: в различни групи, списъци и т.н. С други думи, раздаването на всички елементи в ред би било нетривиална задача.“

„Трето, колекциите са склонни да се променят. Да предположим, че решите да покажете цялото съдържание на колекция, но точно в средата на изхода JVM превключва към друга нишка, която замества половината от елементите на колекцията. Така че instead of изхода получавате кой знае Howво."

"Хм..."

"Но! Това са точно видовете проблеми, които итераторът може да реши. Итераторът е специален обект в рамките на колекция, който, от една страна, има достъп до всички свои лични данни и познава вътрешната си структура, а от друга страна , внедрява публичния интерфейс на Iterator, който позволява на всеки да знае How да работи с него .

"Някои итератори имат вътрешен масив, в който всички елементи на колекцията се копират, когато итераторът е създаден. Това гарантира, че всички последващи промени в колекцията няма да повлияят на броя or реда на елементите."

„Мисля, че сте се сблъскали с това, когато работите с for each . Не можете едновременно да преминавате през колекция и да премахвате елементи от нея. Всичко това се дължи именно на начина, по който работи итераторът.“

„В новите колекции, добавени към библиотеката за едновременност, итераторът е преработен, за да елиминира този проблем.“

„Нека ви напомня How работи итераторът.“

"Java има специален интерфейс на Iterator. Ето неговите методи:"

Методи на интерфейса Iterator<E> Описание
boolean hasNext() Проверява дали има още елементи
E next() Връща текущия елемент и преминава към следващия.
void remove() Премахва текущия елемент

"Итераторът ви позволява последователно да получавате всички елементи на колекция. По-логично е да мислите за итератор като нещо като InputStream - той има всички данни, но задачата му е да ги изведе последователно."

"   Методът next () връща следващия елемент в колекцията."

„ Методът hasNext () се използва за проверка дали има още елементи.“

„И премахване () премахва текущия елемент.“

"НяHowви въпроси?"

"Защо методите имат толкова странни имена? Защо не isEmpty() и getNextElement()?"

— Това няма ли да има повече смисъл?

„Би имало повече смисъл, но имената идват от езика C++, където итераторите се появяват по-рано.“

— Разбирам. Да продължим.

„В допълнение към итератор, има и интерфейс Iterable, който трябва да бъде внедрен от всички колекции, които поддържат итератори. Той има един единствен метод:“

Методи на интерфейса Iterable<T> Описание
Iterator<T>iterator() Връща обект на итератор

„Можете да използвате този метод във всяка колекция, за да накарате обект на итератор да премине през своите елементи. Нека да разгледаме всички елементи на в TreeSet :

Пример
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

while (iterator.hasNext())
{
 String item = iterator.next();
 System.out.println(item);
}

"Използването на итератор като този не е много удобно - има твърде много излишен и очевиден code. Ситуацията стана по-проста, когато цикълът for-each се появи в Java."

„Сега този code е много по-компактен и четим:“

Преди След
TreeSet<String> set = new TreeSet<String>();
Iterator<String> iterator = set.iterator();

while (iterator.hasNext())
{
 String item = iterator.next();
 System.out.println(item);
}
TreeSet<String> set = new TreeSet<String>();

for(String item : set)
{
 System.out.println(item);
}

"Това е един и същ code! Итераторът се използва и в двата случая."

„Просто използването му е скрито в цикъла for-each . Имайте предвид, че codeът вдясно изобщо няма червен текст. Използването на итератора е напълно скрито.“

„ Цикъл for-each да се използва за всички обекти, които поддържат итератори. С други думи, можете да напишете свой собствен клас, да добавите метода iterator () към него и да използвате неговите обекти в конструкция for-each .“

„Уау! Разбира се, нямам желание да пиша свои собствени колекции и итератори, но перспективата все още е примамлива. Ще си отбележа това.“

Освен това има друг популярен тип итератор, който дори има свой собствен интерфейс. Говоря за итератор за списъци, т.е. ListIterator .

„Независимо от тяхната реализация, списъците поддържат реда на елементите, което прави работата с тях чрез итератор малко по-удобна.“

„Ето методите на интерфейса ListIterator <E>:“

Метод Описание
boolean hasNext() Проверява дали има още елементи отпред.
E next() Връща следващия елемент.
int nextIndex() Връща индекса на следващия елемент
void set(E e) Променя стойността на текущия елемент
boolean hasPrevious() Проверява дали има елементи отзад.
E previous() Връща предишния елемент
int previousIndex() Връща индекса на предишния елемент
void remove() Премахва текущия елемент
void add(E e) Добавя елемент в края на списъка.

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

"Е, това е интересно нещо. Къде се използва?"

"Да предположим, че искате да се движите напред и назад в свързан списък. Операцията за получаване ще бъде доста бавна, но операцията next() ще бъде много бърза."

"Хм. Вие ме убедихте. Ще го имам предвид."

„Благодаря, Ели!“