Iterator - це поведінковий шаблон проектування, який дозволяє пройтися по всіх елементах деякого складеного об'єкта. Одним з важливих умов при реалізації патерни є те, що ітератор повинен гарантувати нерозкриття внутрішнього устрою об'єкта.
В Java ітератори дуже активно використовуються в Collection Framework. Для цих цілей створено спеціальний interface з однойменною назвою java.util.Iterator. Інтерфейс містить наступні методи:
- hasNext () - повертає буелове значення в залежності від того, чи є ще елементи в колекції.
- next () - повертає наступний елемент в колекції. Відповідно до API метод повинен кидати NoSuchElementException якщо всі елементи вже пройдені.
- remove () - видаляє елемент, який був повернутий останнім викликом next. До цього методу є деякі питання :) - чому власне він знаходиться в інтерфейсі, адже не кожна колекція дозволяє видаляти елементи, врешті-решт є read only колекції. Саме тому починаючи з Java 1.8 метод remove описаний як default з такою реалізацією за замовчуванням: default void remove ()
Давайте опишемо певний клас і реалізуємо для нього Iterator.
Припустимо у нас є жахливий монстр, який складається з голови, руки і ноги. Для кожної частини є сетер, геттер, а так само для зручності метод, який говорить нам про наявність або відсутність частини.
Клас ітератора можна розмістити в тому ж файлі. Нехай індекс (index) відповідає за так званий курсор в Ітератор. Значення -1 буде встановлено при створенні нового об'єкта. Значення 0, 1 і 2 будуть відповідати голові, руці і нозі.
Реалізуємо методи hasNext, next і remove. До речі, remove годі й реалізовувати починаючи з версії Java 1.8. У цьому випадку буде використана реалізація за замовчуванням (дивіться початок статті).
Реалізація ітератора вийшла не дуже красива. Просто я хотів показати, що ітерованих можна не тільки по колекції, а з будь-якого складеному об'єкту.
Для того, щоб можна було зручніше створювати екземпляр ітератора був введений інтерфейс Iterable з методом iterator (). Можна описати клас Monster як реалізує цей інтерфейс і реалізувати метод iterator таким чином:
До речі, цікаве питання із секретом для любителів патернів проектування: Прикладом якого патерну є метод iterator () в java.util.Collection? Правильна відповідь - Factory Method. Дійсно, рішення про те, який саме итератор створювати віддається на відкуп класам-спадкоємцям (ArrayList, LinkedList, HashSet і так далі).
Якщо є питання - пишіть.