Разница между Java Enumeration и Iterator

120

В чем точная разница между этими двумя интерфейсами? Есть ли Enumerationпреимущества перед употреблением Iterator? Если бы кто-нибудь мог уточнить, была бы признательна справочная статья.

cometta
источник
3
Я использовал поиск Google и первый результат был интересное обсуждение в Javaranch о Перечислении против итератора
В.Гое

Ответы:

142

Взглянув на спецификацию Java API для Iteratorинтерфейса, можно найти объяснение различий между Enumeration:

Итераторы отличаются от перечислений двумя способами:

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

Суть в том, что оба Enumerationи Iteratorбудут давать последовательные элементы, но Iteratorулучшены таким образом, что имена методов короче, и есть дополнительный removeметод. Вот параллельное сравнение:

  Enumeration                     Iterator
  ----------------                ----------------
  hasMoreElement()                hasNext()
  nextElement()                   next()
  N/A                             remove()

Как также упоминается в Спецификациях Java API, более новым программам Iteratorследует отдавать предпочтение Enumeration, поскольку «Iterator занимает место Enumeration в структуре коллекций Java». (Из Iteratorспецификации.)

coobird
источник
9
Я думаю, что в этом ответе отсутствует небольшое объяснение относительно параллелизма.
Maarten Bodewes
@Paul_Draper: правки не должны добавлять новое значение посту, это то, для чего нужны комментарии.
Emil
2
@coobird Вы уверены, что «Перечисления обычно быстрее»? так как Enumeration имеет «блок синхронизации кода внутри nextElement ()», и у нас нет синхронизации в итераторах, которая вызывает ConcurrentModificationException rit ?? Мы называем итераторы, как правило, быстрее, а перечисления немного безопаснее. ??
Канагавелу Сугумар
@KanagaveluSugumar Спасибо, что указали на это. (Я не заметил, что к этому ответу было добавлено дополнительное обсуждение.) Я откатил редактирование, так как оно было не совсем точным.
coobird 05
Я думаю, стоит отметить, что remove () - это необязательный метод в интерфейсе Iterator, и довольно много реализующих классов его не реализуют.
Kutzi
35

Итераторы работают без сбоев . то есть, когда один поток изменяет коллекцию, добавляя / удаляя операции, в то время как другой поток просматривает ее через Iterator, используя hasNext() or next()метод, итератор быстро выходит из строя, выбрасывая ConcurrentModificationException. Безотказное поведение итераторов можно использовать только для обнаружения ошибок. Перечисления, возвращаемые методами таких классов, как Hashtable, Vector, не работают без сбоев, что достигается за счет синхронизации блока кода внутри nextElement()метода, который блокирует текущий объект Vector, что требует много времени.

shaILU
источник
5
Только отчасти верно: это поведение не определено в интерфейсе, это зависит от реализации Iterator. Это правда, что «старые» реализации коллекций в java.util (HashSet, ArrayList и т. Д.) Демонстрируют такое поведение. Однако более новые «параллельные» коллекции никогда не будут генерировать исключение ConcurrentModificationException, они будут перемещаться по коллекции на момент создания итератора. Другие реализации могут показывать все еще иное поведение.
Kutzi
1
Также стоит отметить: «Обратите внимание, что отказоустойчивое поведение не может быть гарантировано, поскольку, вообще говоря, невозможно дать какие-либо жесткие гарантии при наличии несинхронизированной одновременной модификации. Отказоустойчивые операции вызывают исключение ConcurrentModificationException в соответствии с принципом максимального усилия. , было бы неправильно писать программу, правильность которой зависела бы от этого исключения: ConcurrentModificationException следует использовать только для обнаружения ошибок ». docs.oracle.com/javase/7/docs/api/java/util/…
Kutzi
11

«Официально» они должны быть похожи с интерфейсом итератора, поддерживающим дополнительные операции (например, удаление). Как правило, используются итераторы.

Вот из интерфейса javadocs интерфейса перечисления :

ПРИМЕЧАНИЕ. Функциональные возможности этого интерфейса дублируются интерфейсом Iterator. Кроме того, Iterator добавляет необязательную операцию удаления и имеет более короткие имена методов. В новых реализациях следует рассмотреть возможность использования Iterator вместо Enumeration.

Uri
источник
6

Один простой факт, о котором не упоминалось в предыдущих ответах, заключается в том, что Iterator<T>он используется Iterable<T>для интерпретации for(_type_ element:collection){...}структуры.

Земляной двигатель
источник
5

В Enumeration и Iterator есть три основных различия

Перечисление
1. используется только для класса задержки (например Vector).

    Enumeration e = v.elements();  
    v is the object of `Vector` class

2. Операция чтения может быть выполнена, мы не можем удалить элемент.
3. Доступны два метода

  • публичное логическое hasNextElement ();
  • публичный объект nextElement ();

Итератор

  1. применимо для всей коллекции

    Iterator itr = c.iterator();  
    where c is any `Collection` class
    
  2. Операция чтения и удаления может быть выполнена

  3. Доступны три метода

    • общественное логическое hasNext ();
    • публичный объект next ();
    • public void remove ();

Ограничение в обоих

  • Двигаться только вперед
  • Нет никаких методов для Add objectиReplace object
Випин Джайн
источник
2

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

Если по какой-то причине (о которой я не могу придумать) вы создаете собственный класс коллекции, который никак не связан с java.util.Collection или java.util.Map, вам все равно следует реализовать Iterable, чтобы люди могли использовать ваш класс в циклах for.

Лики Линдси
источник
2

Основное отличие заключается в том, что Enumeration не предоставляет метод remove (). Более того, Iterator не допускает одновременной навигации и модификации базового объекта. У них есть контроль, чтобы увидеть, есть ли одновременные модификации или около того, и, следовательно, требуется больше обработки. Таким образом, производительность Enumeration практически на 50% выше, чем у Iterator. Если нам нужна только навигация, игнорирующая такую ​​синхронизацию, просто используйте Enumeration.

bnguyen82
источник
Это правда, что Enumeration «не» предоставляет метод remove (), но оно также не обращает внимания на вызов API remove () Collection. Например, следующий код просто напечатает: AAA, CCC, EEE. -------------------------------------------------- --- Вектор <String> v = новый вектор <String> (6); v.add ( "AAA"); v.add ( "В"); v.add ( "CCC"); v.add ( "DDD"); v.add ( "ЕЕЕ"); v.add ( "FFF"); Перечисление <String> en = v.elements (); while (en.hasMoreElements ()) Строковое значение = (String) en.nextElement (); System.out.println (значение); v.remove (значение);
javauser71
1

1) Основное различие между Iterator и Enumeration - это удаление элемента при обходе коллекции. Итератор может удалить элемент во время обхода коллекции, поскольку у него есть метод remove (). В перечислении нет метода remove ().

2) Перечисление по своей природе отказоустойчиво. Он не генерирует ConcurrentModificationException, если Collection изменяется во время обхода. Итератор по своей природе отказоустойчив. Он выдает исключение ConcurrentModificationException, если Collection изменяется при итерации, отличной от собственного метода remove ().

3) Перечисление - это унаследованный интерфейс, который используется для обхода Vector, Hashtable. Итератор не является устаревшим интерфейсом. Итератор можно использовать для обхода HashMap, LinkedList, ArrayList, HashSet, TreeMap, TreeSet.

Дхирендра Гаутам
источник
0

Перечисление можно использовать только для унаследованного класса (Vector, Stack ...), а Iterator можно использовать для всех.

Джей Шет
источник
-1

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

Паван Кумар
источник
Где вы увидели, что можно использовать Enumeration для наборов ключей Map ??
Kutzi