Какой базовый интерфейс в иерархии коллекций Java расширяет интерфейс Collection?

Ответ

Интерфейс Collection<E> напрямую расширяет интерфейс Iterable<T>. Это делает все коллекции совместимыми с циклом for-each и позволяет получать итератор для обхода элементов.

Ключевые методы Iterable<T>:

  • Iterator<T> iterator() — возвращает итератор для последовательного доступа к элементам.
  • default void forEach(Consumer<? super T> action) — выполняет действие для каждого элемента.

Пример использования:

Collection<String> collection = List.of("A", "B", "C");

// Использование итератора (метод из Iterable)
Iterator<String> it = collection.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}

// Использование for-each (возможно благодаря Iterable)
for (String item : collection) {
    System.out.println(item);
}

Таким образом, Iterable<T> является корневым интерфейсом для всех коллекций, предоставляющим базовый механизм обхода.

Ответ 18+ 🔞

Давай разжую эту тему про Iterable и Collection, чтобы было понятно даже тому, кто только вчера узнал, что Java — это не только остров.

Вот смотри, вся эта вавилонская башня коллекций в Java стоит на одном простом, но ёбарически важном кирпиче — интерфейсе Iterable<T>. Это как базовая лицензия на право ебашить циклом for-each. Если твой класс его реализует — ты в игре, ты теперь коллекция, тебя можно перебирать.

А Collection<E> — это уже его старший сын, который всё унаследовал. То есть любая коллекция — ArrayList, HashSet, даже какая-нибудь LinkedList — она по умолчанию уже Iterable. Это не просто так, это гениально и просто, как тапок.

Что же этот волшебный Iterable<T> умеет?

  • Iterator<T> iterator() — это его главный козырь. Он выдаёт тебе итератор, этакую указку, которой ты можешь ткнуть в каждый элемент по очереди и сказать: "Ты следующий, выходи". Без этого метода — нихуя не коллекция.
  • default void forEach(Consumer<? super T> action) — а это уже дефолтный метод, подарок от бога (ну, от разработчиков Java 8). Позволяет навесить действие на каждый элемент, не заморачиваясь с циклами вручную. Удобно, но под капотом всё тот же итератор.

Пример в деле, чтобы не быть голословным:

Collection<String> collection = List.of("A", "B", "C");

// Старая школа: работаем через итератор напрямую (тот самый метод iterator())
Iterator<String> it = collection.iterator();
while (it.hasNext()) { // Пока есть следующий, блядь
    System.out.println(it.next()); // Достаём его и печатаем
}

// Новая школа (на самом деле уже не новая): магия for-each
// А работает она исключительно потому, что коллекция — Iterable!
for (String item : collection) {
    System.out.println(item);
}

Короче, суть в чём: Iterable<T> — это фундаментальный контракт. Он говорит: "Ребята, кто меня реализует, тот обязуется уметь выдавать штуку, которая пройдётся по всем его внутренностям". И благодаря этому вся экосистема — от простых циклов до стримов — может с этим работать. Ёпта, красота же!