Каковы преимущества интерфейса Iterator в Java?

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

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

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

итератор над коллекцией. Итератор заменяет Перечисление в Рамка коллекций Java. итераторы отличаются от перечислений двумя способами:

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

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

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

Ответ 1

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

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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

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

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

Вы можете узнать больше об интерфейсах из Что такое интерфейс? из учебника Java от Sun.

Ответ 5

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

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

Ищите шаблон дизайна итератора, и здесь: http://en.wikipedia.org/wiki/Iterator

Ответ 6

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

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

Ответ 8

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

Ответ 9

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

Ответ 10

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

Ответ 11

Ну, похоже, первая точка маркера позволяет многопоточным (или однопоточным, если вы прикручиваете) приложениям не блокировать сбор для concurrency нарушений. Например, в .NET вы не можете перечислять и изменять коллекцию (или список или любой IEnumerable) одновременно без блокировки или наследования от методов IEnumerable и overriding (мы получаем исключения).

Ответ 12

Итератор просто добавляет общий способ перебора коллекции элементов. Одной из приятных особенностей является i.remove(), в которой вы можете удалить элементы из списка, который вы повторяете. Если вы просто пытались удалить элементы из списка, то обычно имели бы странные эффекты или бросок и исключение.

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

Ответ 13

Итераторы - один из многих шаблонов проектирования, доступных в java. Шаблоны проектирования можно рассматривать как удобные строительные блоки, стили, использование вашего кода/структуры.

Чтобы узнать больше о шаблоне проектирования Iterator, ознакомьтесь с этим сайтом, где рассказывается об Iterator, а также о многих других шаблонах проектирования. Вот фрагмент с сайта на Iterator: http://www.patterndepot.com/put/8/Behavioral.html

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

Ответ 14

Итераторы могут использоваться против любой коллекции. Они позволяют вам определить алгоритм против коллекции элементов независимо от базовой реализации. Это означает, что вы можете обрабатывать List, Set, String, File, Array и т.д.

Через десять лет вы можете сменить реализацию List на лучшую реализацию, и алгоритм все равно будет работать без проблем.

Ответ 15

Итератор полезен, когда вы имеете дело с коллекциями в Java.

Используйте цикл for (Java1.5) для итерации по коллекции или массиву или списку.

Ответ 16

Интерфейс java.util.Iterator используется в структуре коллекций Java, чтобы разрешить модификацию коллекции, продолжая ее повторять. Если вы просто хотите чистить итерацию по всей коллекции, используйте для каждого вместо нее, но потенциал Iterators - это функциональность, которую вы получаете: дополнительная операция remove() и еще лучше для интерфейса List Iterator, который предлагает добавить() и set(). Оба этих интерфейса позволяют вам перебирать коллекцию и одновременно изменять ее структурно. Пытаясь модифицировать коллекцию, итерации через нее с каждым из них будут вызывать исключение ConcurrentModificationException, обычно потому, что коллекция неожиданно изменяется!

Взгляните на класс ArrayList

В нем есть 2 частных класса (внутренние классы) называемые Itr и ListItr

Они реализуют интерфейсы Iterator и ListIterator соответственно

открытый класс ArrayList..... {//охватывающий класс

  private class Itr implements Iterator<E> {

        public E next() {
            return ArrayList.this.get(index++); //rough, not exact
        }

        //we have to use ArrayList.this.get() so the compiler will
        //know that we are referring to the methods in the 
        //enclosing ArrayList class

        public void remove() {
            ArrayList.this.remove(prevIndex);
        }

        //checks for...co mod of the list
        final void checkForComodification() {  //ListItr gets this method as well
             if (ArrayList.this.modCount != expectedModCount) { 
                 throw new ConcurrentModificationException();
             }
        }
  }

  private class ListItr extends Itr implements ListIterator<E> {
         //methods inherted....
        public void add(E e) {
            ArrayList.this.add(cursor, e);
        }

        public void set(E e) {
            ArrayList.this.set(cursor, e);
        }
  }

}

Когда вы вызываете методы iterator() и listIterator(), они возвращаются новый экземпляр частного класса Itr или ListItr, и поскольку эти внутренние классы являются "внутри" охватывающего класса ArrayList, они могут свободно модифицировать ArrayList без запуска исключения ConcurrentModificationException, если вы не измените список одновременно (с помощью консистенции) через набор() add() или remove() класса ArrayList.