Разница между Iterator и Iterable в Java
В этом посте будут обсуждаться различия между Iterator а также Iterable в Java.
Оба Iterator а также Iterable — это интерфейсы в Java, которые выглядят очень похожими и часто сбивают с толку новичков, но это две разные вещи. Короче говоря, если какой-либо класс реализует Iterable интерфейс, он получает возможность перебирать объект этого класса, используя Iterator.
Теперь давайте подробно обсудим основные различия между ними:
1. Ан Iterable представляет коллекцию, которую можно обойти. Реализация Iterable Интерфейс позволяет объекту использовать цикл for-each. Он делает это, внутренне вызывая iterator() метод на объекте. Например, следующий код работает только как List интерфейс расширяет Collection интерфейс, и Collection интерфейс расширяет Iterable интерфейс.
List
for ( String person : persons ) <
System . out . println ( person ) ;
Обратите внимание, что мы также можем позвонить forEach() метод на итерируемом объекте, начиная с Java 8, который выполняет заданное действие для каждого элемента Iterable . Стоит отметить, что стандартная реализация forEach() также использует for-each для внутреннего использования.
С другой стороны, Iterator — это интерфейс, который позволяет нам перебирать какой-то другой объект, который является какой-то коллекцией. Чтобы перебрать Iterator , мы можем использовать hasNext() + next() методы в цикле while, как показано ниже:
Iterator
while ( iterator . hasNext ( ) ) <
System . out . println ( iterator . next ( ) ) ;
Начиная с Java 8, мы также можем легко перебирать Iterator с помощью forEachRemaining() метод.
Iterator
iterator . forEachRemaining ( System . out :: println ) ;
Можно также использовать Iterator внутри цикла for-each путем переноса преобразование Iterator в Iterable с помощью лямбда:
for ( Integer i : ( Iterable
System . out . println ( i ) ;
2. Любой класс, реализующий Iterable интерфейс должен переопределить iterator() метод, предоставляемый Iterable интерфейс. iterator() метод возвращает Iterator , который затем можно использовать для перебора объекта этого класса.
Любой класс, реализующий Iterator интерфейс должен переопределить hasNext() а также next() методы, предоставляемые Iterator интерфейс. hasNext() метод возвращает true, если итерация содержит больше элементов, а next() метод возвращает следующий элемент в итерации.
3. Iterator экземпляр хранит состояние итерации. Это означает, что он предоставляет служебные методы для получения текущего элемента, проверки существования следующего элемента и перехода к следующему элементу, если он присутствует. Другими словами, Iterator запоминает текущую позицию в коллекции и возвращает следующий по порядку элемент, если он присутствует. Iterable , с другой стороны, не поддерживает никакого такого состояния итерации.
4. Договор на Iterable заключается в том, что он должен создать новый экземпляр Iterator каждый раз, когда iterator() метод называется. Это потому, что Iterator экземпляр поддерживает состояние итерации, и все не будет работать, как если бы реализация возвращала одно и то же Iterator дважды.
5. Для Iterable , мы можем двигаться вперед только в прямом направлении, но некоторые из Iterator субинтерфейс как ListIterator позволяет нам перемещаться вперед и назад по List .
Также, Iterable не предоставляет никакого метода для изменения своих элементов, и мы не можем изменить их с помощью цикла for-each. Но Iterator позволяет удаление элементов из базовой коллекции во время итерации с remove() метод.
Это все о различиях между Iterator и Iterable в Java.
Оценить этот пост
Средний рейтинг 4.53 /5. Подсчет голосов: 66
Голосов пока нет! Будьте первым, кто оценит этот пост.
Сожалеем, что этот пост не оказался для вас полезным!
Расскажите, как мы можем улучшить этот пост?
Зачем в Java 2 интерфейса: Iterable и Iterator?
По-моему они только вносят путаницу. Я так понял их роли: Iterable говорит что по объектам класса в принципе можно итерироваться, а Iterator задает сами методы для итерирования. Но по-моему все это отлично смотрелось бы в одном интерфейсе. Который и объявлял бы класс итерируемым и одновременно задавал бы методы для итерирования.
Отслеживать
задан 8 фев 2016 в 6:30
Александр Елизаров Александр Елизаров
2,788 2 2 золотых знака 18 18 серебряных знаков 36 36 бронзовых знаков
Иногда приходится решать задачи, требующие реализации своих итераторов и Iterable. Вот пример не совсем стандартной работы с коллекциями, здесь нужно обойти две коллекции в определённом порядке. Если бы это была одна сущность, всё было бы заметно сложнее, пришлось бы писать свой класс коллекции. Но благодаря разделению этих интерфейсов, мы можем гибко комбинировать. blog.shamanland.com/2016/03/composite-iterator-ru.html
8 мар 2016 в 14:32
3 ответа 3
Сортировка: Сброс на вариант по умолчанию
Можно было бы об этом задуматься, если предполагаемое соответствие Iterable и его Iterator было «один к одному». Но дело обстоит иначе: Iterable может в некий момент обходиться несколькими Iterator сразу (возможно, ещё и в разных thread’ах!). То есть, это интерфейсы, представляющие две разных сущности: коллекцию и обход коллекции.
Уже поэтому стоит их разделить, поскольку в противном случае для нескольких параллельных обходов коллекция должна быть всегда завёрнута в итератор и иметь два вида копирования (для итератора и для коллекции), а тут уже просматривается явное нарушение SRP (Single Responsibility Principle, принципа единственной обязанности).
Отслеживать
ответ дан 8 фев 2016 в 6:37
user181100 user181100
Один — тот кто ездит. Это Iterator
Другой — тот на ком ездят. Это Iterable
Первый не возможен без Второго. Второй возможен без первого, но бесполезен.
А на самом деле Iterable — всего лишь способ задать стандартный механизм извлечения итератора. Он не является таким уж важным в деле итерации. Он не нужен совсем.
Например у List есть ещё listIterator, к которому Iterable вообще никакого отношения не имеет. но тем не менее это настоящий итератор и даже упруженный дополнительными возможностями.
Отслеживать
ответ дан 8 июн 2017 в 0:20
6,300 1 1 золотой знак 12 12 серебряных знаков 18 18 бронзовых знаков
. все это отлично смотрелось бы в одном интерфейсе
Не смотрелось бы.
Iterator — это интерфейс. То есть мы можем вызвать метод какого-то класса, передать ему итератор и как бы сказать: «вот тебе некая последовательность, пробегись-ка по ней и сделай ряд действий».
Благодаря абстрактности итератор может быть вообще не привязан ни к какой коллекции, а самостоятельно генерировать значения на лету!
Причём эти действия, связанные с последовательным проходом по элементам, одинаковы для любого типа контейнера.
Но даже если считать, что любой итератор завязан на своём контейнере, то всё равно получается нехорошо. Итератор — это вспомогательная сущность, состояние которой надо хранить. Плюс, как правильно заметил @D-side, итератор даже уровне восприятия является отдельной сущностью.
Вопрос №40649 от пользователя Daria Tsvetkova в уроке «Модуль 1. Урок 1. Iterator.», курс «Java: Структуры данных»
interface Iterable находится в пакете java.lang и имплементация этого интерфейса позволяет объекту быть итерируемым с помощью for-each. Из под реализации Iterable можно вызвать iterator . И не один. И даже в нескольких потоках. А может и не использовать итератор вовсе.
interface Iterator находится в пакете java.util . В его имплементации задаются правила обхода коллекции.
Да и названия интерфейсов говорят сами за себя:
- Iterable (какое) — итерируемое. То по чему можно итерироваться. Имплементируется классом, по которому нужно будет итерироваться.
- Iterator (кто/что) — инструмент итерирования по коллекции. Итератор это отдельный класс, как правило вложенный в итерируемый класс, который задает логику итерации по итерируемому. И, естественно, имплементирует интерфейс Iterator .
Iterable. Сравнение с Iterator
Iterable представляет собой простое представление ряда однородных элементов, которые могут повторяться определенное количество раз. Он не имеет никакого итерационного состояния, такого как «текущий элемент». Вместо этого он имеет один метод, который создает Iterator .
Iterator — объект с итерационным состоянием. Он позволяет вам проверить, есть ли у него больше элементов с помощью метода hasNext() и перейти к следующему элементу (если он есть) с помощью метода next() .
Как правило, Iterable должен иметь возможность выдавать любое количество допустимых Iterator-ов.
Реализация Iterable — это та, которая сама предоставляет Iterator :
public interface IterableT> < Iterator iterator(); >
Итератор — это простой способ разрешить некоторым циклическим путем собирать данные без возможности изменения элементов коллекции (хотя и с возможностью их удаления).
public interface IteratorE> < boolean hasNext(); E next(); void remove(); >
Можно рассмотреть эти 2 интерфейса еще с одной стороны:
- Итерируемый (Iterable): Класс, который можно повторить. То есть тот, у которого есть понятие «принесите мне первое, теперь следующее, и так далее, пока мы не закончим».
- Итератор (Iterable): Класс, который управляет итерацией по итерируемому. То есть, он отслеживает, где мы находимся в текущей итерации, и знает, что представляет собой следующий элемент и как его получить.
Чтобы сделать объект итерабельным, он должен возвращать объект Iterator . Чтобы обеспечить выполнение этого контракта, необходимо использовать интерфейс Iterable . Он содержит метод с именем iterator() и возвращает Iterator . Следовательно, любой класс, реализующий Iterable , может вернуть Iterator .
Пример
public interface CollectionE> extends IterableE> <>
Коллекция представляет собой интерфейс, представляющий контейнер для ряда элементов, и все коллекции, такие как ArrayList , LinkedList и т.д. реализуют интерфейсы как Collection , так и Iterable .