Каковы преимущества интерфейса Iterator в Java? - PullRequest
34 голосов
/ 18 сентября 2008

Я только что узнал о том, как Java Collections Framework реализует структуры данных в связанных списках. Из того, что я понимаю, Iterators - это способ обхода элементов в структуре данных, такой как список. Почему этот интерфейс используется? Почему методы hasNext(), next() и remove() не закодированы непосредственно в самой реализации структуры данных?

С веб-сайта Java: текст ссылки

открытый интерфейс Iterator

An итератор над коллекцией. Итератор занимает место Перечисления в Фреймворк коллекций Java. итераторы Отличаться от перечислений можно двумя способами:

  • Итераторы позволяют вызывающему удалить элементы из базового сбор во время итерации с четко определенная семантика.
  • Имена методов были улучшены.
Этот интерфейс член коллекции Java Framework.

Я попытался погуглить и, похоже, не нашел определенного ответа. Может кто-нибудь пролить свет на то, почему Sun решила использовать их? Это из-за лучшего дизайна? Повышенная безопасность? Хорошая ОО практика?

Любая помощь будет принята с благодарностью. Спасибо.

Ответы [ 16 ]

18 голосов
/ 18 сентября 2008

Почему используется этот интерфейс?

Поскольку он поддерживает основные операции, которые позволят клиентскому программисту выполнять итерации по любому виду коллекций (примечание: не обязательно Collection в Object смысле).

Почему методы ... не напрямую закодированы в структуру данных сама реализация?

Они, они просто помечены как Приватные, так что вы не можете проникнуть в них и гадить с ними. Более конкретно:

  • Вы можете реализовать или разбить на подклассы Iterator так, чтобы он делал то, чего не делают стандартные, без необходимости изменять фактический объект, который он повторяет.
  • Для объектов, которые можно обойти, не нужно, чтобы их интерфейсы были загромождены методами обхода, в частности любыми узкоспециализированными методами.
  • Вы можете раздать Iterators любому клиенту, сколько пожелаете, и каждый клиент может пройти в свое время со своей скоростью.
  • Java Iterators из пакета java.util, в частности, сгенерирует исключение, если хранилище, которое их поддерживает, изменено, пока у вас все еще есть Iterator. Это исключение позволяет вам знать, что Iterator теперь может возвращать недопустимые объекты.

Для простых программ, вероятно, ничего из этого не стоит. Однако сложность, которая делает их полезными, быстро сработает.

6 голосов
/ 18 сентября 2008

Вы спрашиваете: «Почему методы hasNext (), next () и remove () не закодированы непосредственно в самой реализации структуры данных?».

Инфраструктура коллекций Java выбирает интерфейс Итератора как внешний для самой коллекции. Обычно, поскольку каждая коллекция Java реализует интерфейс Iterable, Java-программа будет вызывать iterator, чтобы создать свой собственный итератор, чтобы его можно было использовать в цикле. Как уже отмечали другие, Java 5 позволяет нам напрямую использовать итератор с циклом for-each.

Вывод итератора в его коллекцию позволяет клиенту контролировать процесс итерации по коллекции. Один из вариантов использования, который я могу придумать, где это полезно, - это когда неограниченная коллекция, например, все веб-страницы в Интернете для индексации.

В классической книге GoF контраст между внутренними и внешними итераторами четко изложен.

Фундаментальный вопрос - решить, какая сторона контролирует итерацию, итератор или клиент, который использует итератор. Когда клиент контролирует итерацию, итератор называется внешним итератором, а когда итератор управляет им, итератор является внутренним итератором. Клиенты, использующие внешний итератор, должны выполнить обход и явно запросить следующий элемент у итератора. Напротив, клиент передает внутреннему итератору операцию для выполнения, и итератор применяет эту операцию к каждому элементу ....

Внешние итераторы более гибкие, чем внутренние итераторы. Например, легко сравнить две коллекции на равенство с внешним итератором, но практически невозможно с внутренними итераторами ... Но с другой стороны, внутренние итераторы проще в использовании, поскольку они определяют логику итерации для вас.

Пример работы внутренних итераторов см. В API Ruby Enumerable, который имеет внутренние методы итерации, такие как each. В Ruby идея состоит в том, чтобы передать блок кода (то есть замыкание) внутреннему итератору, чтобы коллекция могла позаботиться о своей собственной итерации.

4 голосов
/ 18 сентября 2008

важно держать коллекцию отдельно от указателя. итератор указывает на определенное место в коллекции и, следовательно, не является неотъемлемой частью коллекции. таким образом, например, вы можете использовать несколько итераторов в одной коллекции.

обратной стороной этого разделения является то, что итератор не знает об изменениях, внесенных в коллекцию, по которой он итерирует. поэтому вы не можете изменить структуру коллекции и ожидать, что итератор продолжит свою работу без «жалоб».

3 голосов
/ 18 сентября 2008

Несколько экземпляров интегратора могут использоваться одновременно. Подойдите к ним в качестве локальных курсоров для базовых данных.

Кстати: предпочтение интерфейсов конкретным реализациям приводит к потере связи

Найдите шаблон проектирования итератора, и здесь: http://en.wikipedia.org/wiki/Iterator

3 голосов
/ 18 сентября 2008

Использование интерфейса Iterator позволяет любому классу, который реализует свои методы, действовать как итераторы. Понятие интерфейса в Java должно иметь, в некотором смысле, договорное обязательство предоставлять определенные функциональные возможности в классе, который implements интерфейс, действовать так, как этого требует интерфейс. Поскольку договорные обязательства должны быть выполнены, чтобы быть действительным классом, другие классы, которые видят класс implements в интерфейсе и, таким образом, успокаиваются, узнав, что класс будет иметь эти определенные функциональные возможности.

В этом примере вместо реализации методов (hasNext(), next(), remove()) в самом классе LinkedList класс LinkedList объявит, что это implements интерфейс Iterator, поэтому другие знают, что LinkedList может быть использован в качестве итератора. В свою очередь, класс LinkedList будет реализовывать методы из интерфейса Iterator (например, hasNext()), поэтому он может функционировать как итератор.

Другими словами, реализация интерфейса является концепцией объектно-ориентированного программирования, позволяющей другим знать, что определенный класс имеет то, что требуется, чтобы быть тем, кем он себя утверждает.

Это понятие обеспечивается применением методов, которые должны быть реализованы классом, реализующим интерфейс. Это гарантирует, что другие классы, которые хотят использовать класс, реализующий интерфейс Iterator, будут действительно иметь методы, которые должны иметь итераторы, такие как hasNext().

Кроме того, следует отметить, что поскольку Java не имеет множественного наследования, использование интерфейса может использоваться для эмуляции этой функции. Реализуя несколько интерфейсов, можно иметь класс, который является подклассом, чтобы наследовать некоторые функции, но также «наследовать» функции другого путем реализации интерфейса. Например, если бы я хотел иметь подкласс класса LinkedList с именем ReversibleLinkedList, который мог бы выполнять итерацию в обратном порядке, я мог бы создать интерфейс с именем ReverseIterator и обеспечить, чтобы он предоставлял метод previous(). Поскольку LinkedList уже реализует Iterator, в новом обратимом списке будут реализованы интерфейсы Iterator и ReverseIterator.

Подробнее об интерфейсах вы можете узнать из Что такое интерфейс? из руководства по Java от Sun.

2 голосов
/ 18 сентября 2008

Потому что вы можете перебирать что-то, что не является структурой данных. Допустим, у меня есть сетевое приложение, которое извлекает результаты с сервера. Я могу вернуть обертку Iterator вокруг этих результатов и передать их через любой стандартный код, который принимает объект Iterator.

Думайте об этом как о ключевой части хорошего дизайна MVC. Данные должны как-то попасть из Модели (то есть структуры данных) в Представление. Использование Iterator в качестве посредника гарантирует, что реализация Модели никогда не будет выставлена. Вы можете хранить LinkedList в памяти, извлекать информацию из алгоритма дешифрования или оборачивать вызовы JDBC. Это просто не имеет значения для представления, потому что представление заботится только об интерфейсе Итератора.

1 голос
/ 18 сентября 2008

В конечном счете, поскольку Iterator захватывает абстракцию управления, которая применима к большому количеству структур данных. Если вы знакомы с вашей теорией категорий, вы можете поразить вас этой статьей: Суть шаблона итератора .

1 голос
/ 18 сентября 2008

Просто M2C, если вы не знали: вы можете избежать непосредственного использования интерфейса итератора в ситуациях, когда достаточно цикла для каждого .

1 голос
/ 18 сентября 2008

Я думаю, что это просто хорошая ОО практика. Вы можете иметь код, который работает со всеми видами итераторов и даже дает вам возможность создавать свои собственные структуры данных или просто общие классы, которые реализуют интерфейс итератора. Вам не нужно беспокоиться о том, какая реализация стоит за этим.

1 голос
/ 18 сентября 2008

Интересная статья, обсуждающая преимущества и недостатки использования итераторов:

http://www.sei.cmu.edu/pacc/CBSE5/Sridhar-cbse5-final.pdf

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...