Java列挙とイテレータの違い


回答:


142

IteratorインターフェースのJava API仕様を見ると、次の違いの説明がありますEnumeration

イテレータは、次の2つの点で列挙と異なります。

  • イテレータを使用すると、明確に定義されたセマンティクスでの反復中に、呼び出し元が基になるコレクションから要素を削除できます。
  • メソッド名が改善されました。

一番下の行は、両方でEnumerationありIterator、連続する要素を提供しますがIterator、メソッド名が短くなるように改善され、メソッドが追加されていremoveます。並べて比較します:

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

Java API仕様でも述べられているように、「イテレータはJavaコレクションフレームワークの列挙の代わりになる」Iteratorので、新しいプログラムではを優先する必要がEnumerationあります。(Iterator仕様より)


9
同時実行性に関して、この回答には少し説明が欠けていると思います。
Maarten Bodewes

@Paul_Draper:編集によって投稿に新しい意味が加わってはなりません。それがコメントの目的です。
エミル

2
@coobird「列挙型は通常、より高速です」と確信していますか?Enumerationには「nextElement()内のコードの同期ブロック」があるため、イテレータでの同期がなく、ConcurrentModificationException ritが発生しますか?イテレータは通常、より高速であり、列挙は少し安全です。??
Kanagavelu Sugumar 2013年

@KanagaveluSugumar指摘いただきありがとうございます。(この回答に追加のディスカッションが追加されたことに気付きませんでした。)完全に正確ではなかったため、編集をロールバックしました。
coobird 2013年

remove()はIteratorインターフェースのオプションのメソッドであり、実装クラスの多くはそれを実装していないことを指摘する価値があると思います。
Kutzi 14

35

イテレータはフェイルファストです。つまり、あるスレッドが追加/削除操作によってコレクションを変更しているときに、別のスレッドがIterator using hasNext() or next()メソッドを使用してコレクションをトラバースしているときに、イテレータがスローすると失敗しますConcurrentModificationException。イテレータのフェイルファスト動作は、バグを検出するためにのみ使用できます。Hashtable、Vectorなどのクラスのメソッドによって返される列挙型は、nextElement()多くの時間を要する現在のVectorオブジェクトをロックするメソッド内のコードのブロックを同期することによって実現されるフェイルファストではありません。


5
一部だけ正しい:この動作はインターフェースで定義されておらず、イテレーターの実装次第です。java.utilの「古い」コレクション実装(HashSet、ArrayListなど)がこの動作を示すことは事実です。ただし、新しい 'concurrent'コレクションはConcurrentModificationExceptionをスローすることはなく、イテレータの作成時にコレクションをトラバースします。他の実装では、まだ異なる動作を示す場合があります。
Kutzi 14

1
また、指摘する価値があります:「フェイルファスト動作は、一般的に言えば、非同期の同時変更が存在する場合にハードな保証を行うことが不可能であるため、保証できないことに注意してください。フェイルファスト操作は、ベストエフォートベースでConcurrentModificationExceptionをスローします。したがって、 、その正確さのためにこの例外に依存するプログラムを書くのは間違っているでしょう:ConcurrentModificationExceptionはバグを検出するためにのみ使用されるべきです。docs.oracle.com/javase/7/docs/api/java/util/...
Kutzi

11

「公式に」、それらは追加の操作(たとえば、削除)をサポートするイテレータインターフェースと同様であると想定されています。一般的には、反復子を使用する傾向があります。

以下は列挙インターフェースjavadocsからのものです。

注:このインターフェースの機能は、Iteratorインターフェースと同じです。さらに、Iteratorはオプションの削除操作を追加し、メソッド名が短くなっています。新しい実装では、列挙よりもイテレータの使用を検討する必要があります。


6

単純な事実の1つですが、これまでの回答で言及していなかったことは、構造の解釈に役立つためにでIterator<T>使用されることです。Iterable<T>for(_type_ element:collection){...}


5

EnumerationとIteratorには基本的な3つの違いがあります

列挙
1.それだけでlagacyクラスの使用である(例えば。Vector

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

2.読み取り操作を実行できますが、要素を削除できません。
3. 2つの方法が利用可能です

  • public boolean hasNextElement();
  • public Object nextElement();

イテレータ

  1. すべてのコレクションに適用されます

    Iterator itr = c.iterator();  
    where c is any `Collection` class
    
  2. 読み取りおよび削除操作を実行できます

  3. 3つの方法が利用可能です

    • public boolean hasNext();
    • public Object next();
    • public void remove();

両方の制限

  • 前方にのみ移動
  • 以下のためのいずれかの方法何もありませんAdd objectし、Replace object

2

独自のコレクションクラスを作成し、既存のクラスを拡張するか、コレクションフレームワークインターフェイスを実装する場合、基本的にはイテレーターを使用するしかありません。

なんらかの理由で(私には考えられない)java.util.Collectionまたはjava.util.Mapにまったく関係のないカスタムコレクションクラスを作成している場合でも、人々が使用できるようにIterableを実装する必要がありますクラスをforループに入れます。


2

主な違いは、列挙がremove()メソッドを公開しないことです。さらに、Iteratorは、基礎となるオブジェクトのナビゲーションと変更を同時に許可しません。彼らは、同時変更などがあるかどうかを確認するコントロールを持っているため、より多くの処理が必要です。したがって、列挙のパフォーマンスはイテレーターよりも実質的に50%高速です。このような同期を無視してナビゲーションのみが必要な場合は、列挙を使用します。


Enumerationがremove()メソッドを公開しないことは事実ですが、コレクションのremove()APIの呼び出しにも注意を払いません。たとえば、次のコードは単にAAA、CCC、EEEを出力します。-------------------------------------------------- --- Vector <String> v = new Vector <String>(6); v.add( "AAA"); v.add( "BBB"); v.add( "CCC"); v.add( "DDD"); v.add( "EEE"); v.add( "FFF"); Enumeration <String> en = v.elements(); while(en.hasMoreElements())String value =(String)en.nextElement(); System.out.println(value); v.remove(value);
javauser71 2013年

1

1)イテレータと列挙の主な違いは、コレクションをトラバースする際の要素の削除です。イテレータは、remove()メソッドを備えているため、コレクションのトラバーサル中に要素を削除できます。列挙には、remove()メソッドはありません。

2)列挙は本質的にフェイルセーフです。トラバーサル中にコレクションが変更されても、ConcurrentModificationExceptionはスローされません。イテレータは本質的にフェイルファストです。独自のremove()メソッド以外の反復中にコレクションが変更されると、ConcurrentModificationExceptionをスローします。

3)列挙は、Vector、Hashtableのトラバースに使用されるレガシーインターフェイスです。イテレータはレガシーインターフェイスではありません。イテレータはHashMap、LinkedList、ArrayList、HashSet、TreeMap、TreeSetのトラバーサルに使用できます。


0

列挙はレガシークラス(Vector、Stack ...)にのみ使用できますが、Iteratorはすべてに使用できます。


-1

反復子と列挙型の両方を使用してデータを取得します。違いは、列挙型はレガシークラス(ベクトル/スタック)にのみ使用できるのに対し、反復子は残りに使用できることです。列挙は、マップに設定されたキーにも使用できます。


MapのキーセットにEnumerationを使用できることはどこでわかりましたか?
Kutzi 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.