Різниця між перерахуванням Java та ітератором


120

Яка точна різниця між цими двома інтерфейсами? Чи Enumerationє переваги від використання Iterator? Якщо хтось міг би детально розробити, посилається на довідкову статтю.


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, оскільки "Ітератор займає місце перерахування в рамках колекцій Java". (Із Iteratorспецифікацій.)


9
Я думаю, що у цій відповіді щодо одночасності не вистачає пояснень.
Maarten Bodewes

@Paul_Draper: Зміни не повинні додавати нове значення до публікації, саме для цього є коментарі.
Еміль

2
@coobird Ви впевнені, що "Перерахування зазвичай швидше"? оскільки перелік має "блок синхронізації коду в nextElement ()", і у нас немає синхронізації в ітераторах, що викликає ритм ConcurrentModificationException ?? Чи називаємо ми ітераторів, як правило, швидшими, а перерахування - трохи безпечнішими. ??
Канагавелу Сугумар

@KanagaveluSugumar Дякую, що вказали на це. (Я не помітив, що до цієї відповіді було додано додаткове обговорення.) Я відкрутив правки, оскільки це було не зовсім точно.
coobird

Я думаю, що варто зазначити, що delete () - необов'язковий метод в інтерфейсі Iterator, і досить багато класів реалізації не реалізують його.
Kutzi

35

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


5
Вірно лише частково: така поведінка не визначена в інтерфейсі, це залежить від реалізації Ітератора. Це правда, що "стара" реалізація колекції в java.util (HashSet, ArrayList тощо) проявляє таку поведінку. Однак новіші "одночасні" колекції ніколи не викидають ConcurrentModificationException, вони пройдуть колекцію на момент створення ітератора. Інші реалізації можуть демонструвати все-таки різну поведінку.
Kutzi

1
Також варто зазначити: "Зауважте, що невдала поведінка не може бути гарантована, оскільки це, взагалі кажучи, неможливо дати будь-які жорсткі гарантії за наявності несинхронізованої одночасної модифікації. Невдалі операції кидають ConcurrentModificationException на основі найкращих зусиль. Тому , було б неправильно писати програму, яка залежала від цього винятку за її правильність: ConcurrentModificationException слід використовувати лише для виявлення помилок. " docs.oracle.com/javase/7/docs/api/java/util/…
Kutzi

11

"Офіційно" вони повинні бути подібними до інтерфейсу ітератора, який підтримує додаткові операції (наприклад, видалення). Як правило, тенденція до використання ітераторів.

Ось з інтерфейсу перерахування javadocs :

ПРИМІТКА. Функціонал цього інтерфейсу дублюється інтерфейсом Iterator. Крім того, Iterator додає необов'язкову операцію видалення та має більш короткі назви методів. Новим реалізаціям слід розглянути можливість використання Iterator у перевазі «Перерахування».


6

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


5

Існує три основні відмінності в Перерахуванні та Ітераторі

Перерахування
1. це використання лише для класів, що мають відставання (наприклад, Vector)

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

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

  • public boolean hasNextElement ();
  • загальнодоступний об’єкт nextElement ();

Ітератор

  1. він застосовується для всієї колекції

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

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

    • public boolean hasNext ();
    • громадський об’єкт next ();
    • public void remove ();

Обмеження в обох

  • Рухайтеся лише вперед в напрямку
  • Існує ніяких методів для Add objectіReplace object

2

Якщо ви пишете свій власний клас колекції та розширюєте будь-який із існуючих класів або впроваджуєте будь-який із рамкових інтерфейсів Collections, вам в основному не залишається іншого вибору, як використовувати Iterator.

Якщо з якихось причин (про що я не можу придумати) ви створюєте спеціальний клас колекції, який жодним чином не стосується java.util.Collection або java.util.Map, вам все одно слід застосувати Iterable, щоб люди могли використовувати ваш клас для циклів.


2

Основне відмінність - це перерахування не викриває метод delete (). Крім того, Iterator не дозволяє одночасно переходити та змінювати базовий об'єкт. Вони мають контроль, щоб побачити, чи є одночасні модифікації чи так, і тому потрібно більше обробки. Тож продуктивність Enumeration практично на 50% швидша, ніж Iterator. Якщо нам потрібна лише навігація, ігноруючи таку синхронізацію, просто використовуйте Перерахування.


Це правда, що «Перерахування» не «викриває» метод видалення (), але він також не звертає уваги на виклик api колекції delete (). Наприклад, наступний код буде просто надрукований: AAA, CCC, EEE. -------------------------------------------------- --- вектор <String> v = новий вектор <String> (6); v.add ("AAA"); v.add ("BBB"); v.add ("CCC"); v.add ("DDD"); v.add ("EEE"); v.add ("FFF"); Перерахування <String> en = v.elements (); while (en.hasMoreElements ()) String value = (String) en.nextElement (); System.out.println (значення); v.remove (значення);
javauser71

1

1) Основна відмінність Ітератора від Перерахування - це видалення елемента під час проходження колекції. Ітератор може видалити елемент під час обходу колекції так, як він має метод delete (). Перерахування не має методу remove ().

2) Перерахування є безпечним за своєю суттю. Він не кидає ConcurrentModificationException, якщо колекція буде змінена під час обходу. Ітератор невдалий за своєю природою. Він кидає ConcurrentModificationException, якщо колекцію модифікують під час ітерації, відмінного від її власного методу delete ().

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


0

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


-1

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


Де ви бачили, що ви можете використовувати перерахування для ключових наборів Map ??
Kutzi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.