Ответ
Итератор (Iterator) — это паттерн, предоставляющий стандартный способ последовательного доступа к элементам коллекции без раскрытия её внутренней структуры.
Интерфейс java.util.Iterator<E>:
public interface Iterator<E> {
boolean hasNext();
E next();
default void remove() { ... }
default void forEachRemaining(Consumer<? super E> action) { ... }
}
Реализация собственного итератора:
- Класс коллекции должен реализовать интерфейс
Iterable<T>, который требует методiterator(). - Метод
iterator()возвращает экземпляр класса, реализующегоIterator<T>.
Пример для простой коллекции:
public class CustomCollection<T> implements Iterable<T> {
private T[] elements;
@Override
public Iterator<T> iterator() {
return new CustomIterator();
}
private class CustomIterator implements Iterator<T> {
private int cursor = 0;
@Override
public boolean hasNext() {
return cursor < elements.length && elements[cursor] != null;
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return elements[cursor++];
}
}
}
Использование:
CustomCollection<String> collection = new CustomCollection<>();
for (String item : collection) { // Использует foreach (требует Iterable)
System.out.println(item);
}
Важно: Итераторы в Java являются fail-fast для большинства стандартных коллекций (например, ArrayList) — при модификации коллекции во время итерации (кроме через remove() самого итератора) выбрасывается ConcurrentModificationException.
Ответ 18+ 🔞
А, ну слушай, вот есть у тебя куча всякого барахла — массив там, список, черт знает что. И тебе надо по нему пройтись, да? Ну, тупо циклом. Но это же скучно, как говно засохшее, и каждый раз одно и то же. А если коллекция у тебя хитрая, блядь, своя собственная? Ты же не будешь всем подряд выворачивать её кишки наружу, показывая, как она там внутри устроена? Вот для этого и придумали итератор, ёпта!
Представь себе, это такой универсальный пульт управления для прохода по коллекции. Как пульт от телика — тебе же похуй, что там внутри, микросхемы какие, ты просто кнопки жмёшь: «следующий», «следующий». Вот и тут так же.
В Яве для этого есть готовый интерфейс java.util.Iterator<E>. Выглядит он просто, хуй с горы:
public interface Iterator<E> {
boolean hasNext(); // Есть ли ещё что посмотреть, или уже всё, пиздец?
E next(); // Дай следующую штуку, я жду!
default void remove() { ... } // Опционально: удали ту штуку, которую только что дал (осторожно, блядь!)
default void forEachRemaining(Consumer<? super E> action) { ... } // Ну это чтоб не париться, прогнать всё оставшееся
}
Теперь, если ты делаешь свою коллекцию и хочешь, чтобы по ней можно было красиво пройтись циклом for-each (это который for (String s : myCollection)), то тебе надо сделать её Iterable. А это значит — реализовать один-единственный метод iterator(), который вернёт тебе свеженький итератор.
Вот смотри, как это выглядит на практике для какой-нибудь простой коллекции:
public class CustomCollection<T> implements Iterable<T> {
private T[] elements; // Допустим, тут у нас хранится всё добро
@Override
public Iterator<T> iterator() {
return new CustomIterator(); // Возвращаем свой собственный, самодельный итератор
}
// А вот и он, красавец, спрятан внутри как внутренний класс
private class CustomIterator implements Iterator<T> {
private int cursor = 0; // Индекс, который помнит, где мы остановились
@Override
public boolean hasNext() {
// Проверяем, не упёрлись ли мы в конец и не наткнулись ли на null
return cursor < elements.length && elements[cursor] != null;
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException(); // Если больше ничего нет — нахуй так делать, исключение летит
}
// Берём элемент и двигаем курсор вперёд
return elements[cursor++];
}
}
}
И теперь использование — просто песня, блядь:
CustomCollection<String> collection = new CustomCollection<>();
// И можно тупо через foreach, потому что класс — Iterable
for (String item : collection) {
System.out.println(item);
}
Но есть один важный момент, ёбаный в рот! Итераторы в стандартных коллекциях Java (типа ArrayList) — они fail-fast. Это значит, что если ты начал итерироваться по коллекции, а потом где-то сбоку её изменил (добавил или удалил элемент, кроме как через метод remove() самого итератора), то в следующем же шаге тебе вылетит ConcurrentModificationException. Мол, «чувак, бля, коллекция изменилась, я нихуя не понимаю, где я теперь нахожусь, всё, пиздец, я сваливаю». Так что с этим надо аккуратнее, ебушки-воробушки.