Главная » Java » Итераторы в составе интерфейса Collection

0

 

   В составе интерфейса Collection предусмотрен метод iterator, которы возвращает объект класса, реализующего интерфейс Iterator. Ниже описан методы интерфейса Iterator.

 

public boolean hasNext()

Возвращает true, если объект итератора способен вернуть очередной элемент коллекции.

public Object next()

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

public void  remove ()

Удаляет из коллекции элемент, который был возвращен последним вызовом метода next итератора. Метод remove может быть вызван только один раз после каждого обращения к next. Если next не вызывался вообще либо после момента последнего обращения к next метод remove уже активизировался, выбрасывается исключение типа illegalStateException. (Реализация метода в производных классах не обязательна.)

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

 

public void  removeLongStrings(Collection coll,   int maxLen)   {

    Iterator it = coll .iterator() ;

    while  (it.hasNext())   {

         String str = (String)it.next();

          if (str.length()  > maxLen)

             it.remove();

   }

}

Метод iterator объекта Collection используется для получения объекта Iterator, позволяющего просматривать содержимое коллекции элемент за элементом. Процесс выполняется в цикле, и условием его завершения служит значение false, возвращаемое методом hasNext, позволяющим определить, существуют ли элементы коллекции, к которым итератор еще не обращался. На каждой итерации цикла с помощью метода next возвращается очередной элемент коллекции. Если длина элемента-строки превышает заданный предел maxLen, для удаления этого элемента, возвращенного методом next последним, вызывается метод remove итератора. Использование remove для изменения содержимого коллекции в контексте текущего итератора совершенно безопасно — итератор успешно продолжит свой "путь" по оставшимся элементам коллекции. Удаление элементов коллекции какими-либо иными способами (посредством операций над объектом коллекции как таковым либо с помощью другого итератора, построенного для той же коллекции) в общем случае чревато недоразумениями и ошибками.

  Интерфейс Listlterator расширяет Iterator, добавляя методы, которые могут быть использованы для манипуляции содержимым упорядоченного списка Li St. Для осуществления итерации от начала к концу списка применяются ме-ТоДы hasNext и next, а для обратного перемещения по списку — hasPrevious и Previous, причем операции движения "вперед" и "назад" могут выполняться в любой последовательности и перемежаться. Следующий код показывает, как следует осуществлять процесс итерации от конца к началу списка:

 

 

Listlterator  it = list.listlterator(list.size()) ;

   while  (it.hasPrevious())   {

     Object obj = it.previous() ;

     System.out.println(obj);

   // … обработка obj …

}

Выражение в первой строке кода позволяет создать объект итератора и установить его внутренний указатель на позиции, следующей за завершающим элементом списка. Далее выполняется циклическое обращение к каждому элементу списка, начиная с последнего, и его содержимое выводится на экран. Элементы списка индексируются по значению занимаемой ими позиции — точно так же, как и элементы обычного массива, — от 0 до list.size()-l. Методы nextlndex и previouslndex позволяют получить значения индексов элементов, которые будут возвращены при очередном вызове next или previous соответственно. Если указатель итератора находится в конце списка, вызов nextlndex вернет значение list.size(). Если же указатель итератора расположен в начале списка (на элементе с индексом 0), при обращении к методу previouslndex будет получено значение

-1.

   Метод remove объекта Listlterator удаляет элемент, который был возвращен при последнем обращении к любому из методов, next или previous. Помимо remove, в составе интерфейса Listlterator определены два других метода, позволяющих изменять содержимое списка.

public void set(Object elem)

Заменяет содержимое элемента, возвращенного при последнем обращении к любому из методов, next или previous, значением elem. Если после момента последнего обращения к next или previous вызывались методы remove или add итератора, при попытке использования set будет выброшено исключение типа il legal StateException. (Реализация метода в производных классах не обязательна.)

public void add(Object elem)

Вставляет объект elem перед очередным элементом списка, который был бы возвращен при вызове next, либо в конец списка, если hasNext возвращает значение false. Указатель итератора перемещается вперед — если после вызова add обратиться к previous, будет возвращен вставленный элемент. (Реализация метода в производных классах не обязательна.)

Контракт   метода   remove   в   Listlterator   расширен—   исключение   типа Illegal StateException выбрасывается в том случае, если между попыткой активизации     remove     и    более     ранним    вызовом     next     или     previous "вклинивается" обращение к set либо add.

   Контракты интерфейсов Iterator и Listlterator не содержат гарантий обеспечения достоверности данных при использовании наряду с итератором альтернативных средств изменения содержимого коллекции. Иными словами, если содержимое списка изменяется в то время, когда итератор активен, это может повлиять на результаты работы его методов. Если, например, в реализации next предусмотрено использование элементов исходного содержимого коллекции, удалять элементы сп ска,  "обходя" собственные методы итератора, предназначенные для той же цел . весьма опасно. Для преодоления подобных проблем может использоваться техноло гия    моментальных    снимков    (snapshots),     когда    итератор     Iterator    ил^ Listlterator возвращает элементы коллекции в том виде, в каком они пребывал на момент создания самого итератора, и гарантирует тем самым устойчивость поЛ чаемых   результатов   по   отношению   к   возможным   изменениям,   инициируемы "извне". Вы можете доверять подобным средствам только в том случае, если котракт метода, возвращающего объект итератора, явно декларирует поддержку технологии моментальных снимков. Если потребность в использовании такой технологии существует, но гарантии ее поддержки отсутствуют, вы можете создать моментальный снимок самостоятельно, выполнив простое копирование содержимого коллекции, — например, следующим образом:

public iterator snapshotlterator(Collection coll)   {

    return new ArrayList(coll).iterator();

Многие из итераторов, определенных в пакете java.util, можно отнести к категории итераторов, чувствительных к нарушениям (fail-fast iterators). Подобные итераторы способны выявить факт изменения данных коллекции, осуществленного альтернативными средствами, которые не относятся к сфере компетенции самого’ итератора, а затем быстро и изящно отреагировать выбрасыванием исключения типа ConcurrentModificationException — вместо того, чтобы продолжать работу, не обеспечивая при этом гарантий достоверности возвращаемых результатов.

 

Источник: Арнолд, Кен, Гослинг, Джеймс, Холмс, Дэвид. Язык программирования Java. 3-е изд .. : Пер. с англ. – М. : Издательский дом «Вильяме», 2001. – 624 с. : ил. – Парал. тит. англ.

По теме:

  • Комментарии