技術空間

Java

EnumerationとIteratorの違い


TOP > Java > EnumerationとIteratorの違い



■EnumerationとIteratorの違い

Mapのキーや値を取得して繰り返し処理を行いたい場合、EnumerationもしくはIteratorを使う。 どちらもjava.util配下のインタフェースである。

IteratorはEnumerationの改良版であり、Enumerationは古くからあるAPIでしか使用されていない。 Enumerationの公式Javadocにも、新しく実装する場合にはIteratorを使うよう言及されている。

では何が改良されたのか?これはIterator側のJavadocに記載されている。

EnumerationとIteratorのメソッドは数個しかない。以下、比較表。

メソッドEnumerationIterator
要素の有無判定hasMoreElements()hasNext()
次の要素取得nextElement()next()
要素削除-remove()

このようにIteratorではメソッド名が短くなっているのと、要素削除メソッドが追加されている。

では、EnumerationとIteratorのサンプルコードを使って動作を確認してみる。

■Enumerationのサンプルコード

まずはHashMapのキーと値を標準出力に表示。

Mapインタフェースには直接Enumerationで取得するメソッドがないため、Collections.enumeration()を使う。

コード
Map<String, String> map = new HashMap();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");
map.put("key5", "value5");

Enumeration<String> keys = Collections.enumeration(map.keySet());
while(keys.hasMoreElements()) {
    System.out.println(keys.nextElement());
}

Enumeration<String> values = Collections.enumeration(map.values());
while(values.hasMoreElements()) {
    System.out.println(values.nextElement());
}
出力結果
key1
key2
key5
key3
key4
value1
value2
value5
value3
value4

キーと値が出力されているのがわかる。HashMapは順序性を持たないので、設定した順と関係なく、順不同で表示されている。

次はHashtableで試してみる。HashtableはキーのみEnumerationで取得するkeysメソッドが用意されている。

コード
Hashtable<String, String> hashT = new Hashtable();
hashT.put("key1", "value1");
hashT.put("key2", "value2");
hashT.put("key3", "value3");
hashT.put("key4", "value4");
hashT.put("key5", "value5");

Enumeration<String> keys = hashT.keys();
while(keys.hasMoreElements()) {
    System.out.println(keys.nextElement());
}

Enumeration<String> values = Collections.enumeration(hashT.values());
while(values.hasMoreElements()) {
    System.out.println(values.nextElement());
}
出力結果
key5
key4
key3
key2
key1
value5
value4
value3
value2
value1

Hashtableも順不同で表示されている。

次はLinkedHashMapで試してみる。使い方はほぼHashMapと同じ。

コード
Map<String, String> map = new LinkedHashMap();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");
map.put("key5", "value5");

Enumeration<String> keys = Collections.enumeration(map.keySet());
while(keys.hasMoreElements()) {
    System.out.println(keys.nextElement());
}

Enumeration<String> values = Collections.enumeration(map.values());
while(values.hasMoreElements()) {
    System.out.println(values.nextElement());
}
出力結果
key1
key2
key3
key4
key5
value1
value2
value3
value4
value5

LinkedHashMapは順序性を保つので、設定した順番に出力される。

最後に繰り返し処理中に要素を削除してみる。Enumeration自体には削除メソッドがないため、Mapのremoveメソッドで削除。

コード
Map<String, String> map = new HashMap();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");
map.put("key5", "value5");

Enumeration<String> keys = Collections.enumeration(map.keySet());
while(keys.hasMoreElements()) {
    String key = keys.nextElement();
    if("key3".equals(key)){
        map.remove(key);
    }
    System.out.println(key);
}
出力結果
key1
key2
key5
key3
Exception in thread "main" java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextNode(Unknown Source)
        at java.util.HashMap$KeyIterator.next(Unknown Source)
        at java.util.Collections$3.nextElement(Unknown Source)
        at Sample.sampleRemoveData(Sample.java:92)
        at Sample.main(Sample.java:11)

削除する時に例外が発生する。この例外は要素の整合性が保てなくなった際に発生する例外である。このようにEnumerationを使うと繰り返し中に要素の削除ができない。

■Iteratorのサンプルコード

次にIteratorのサンプル。

まずは先ほどと同様HashMapのキーと値を標準出力に表示してみる。

MapインタフェースのkeySet()、values()の戻り値がCollectionインタフェースを実装しているため、Collectionのiterator()を使ってIteratorを取得する。

コード
Map<String, String> map = new HashMap();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");
map.put("key5", "value5");

Iterator<String> keys = map.keySet().iterator();
while(keys.hasNext()) {
    System.out.println(keys.next());
}

Iterator<String> values = map.values().iterator();
while(values.hasNext()) {
    System.out.println(values.next());
}
出力結果
key1
key2
key5
key3
key4
value1
value2
value5
value3
value4

結果はEnumerationの時と同様。

次はHashtableで試してみる。キーはkeys()ではなくkeySet()を使う。

コード
Hashtable<String, String> hashT = new Hashtable();
hashT.put("key1", "value1");
hashT.put("key2", "value2");
hashT.put("key3", "value3");
hashT.put("key4", "value4");
hashT.put("key5", "value5");

Iterator<String> keys = hashT.keySet().iterator();
while(keys.hasNext()) {
    System.out.println(keys.next());
}

Iterator<String> values = hashT.values().iterator();
while(values.hasNext()) {
    System.out.println(values.next());
}
出力結果
key5
key4
key3
key2
key1
value5
value4
value3
value2
value1

HashtableもEnumerationと同様の出力結果となる。

次はLinkedHashMap。

コード
Map<String, String> map = new LinkedHashMap();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");
map.put("key5", "value5");

Iterator<String> keys = map.keySet().iterator();
while(keys.hasNext()) {
    System.out.println(keys.next());
}

Iterator<String> values = map.values().iterator();
while(values.hasNext()) {
    System.out.println(values.next());
}
出力結果
key1
key2
key3
key4
key5
value1
value2
value3
value4
value5

LinkedHashMapもEnumerationと同様の出力結果。

ここまではEnumerationとIteratorで動きに違いはない。

では次に要素の削除を実施してみる。Iteratorのremoveメソッドを使って削除する。

コード
Map<String, String> map = new HashMap();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
map.put("key4", "value4");
map.put("key5", "value5");

Iterator<String> keys = map.keySet().iterator();
while(keys.hasNext()) {
    String key = keys.next();
    if("key3".equals(key)){
        keys.remove();
    }
    System.out.println(key);
}

System.out.println(map);
出力結果
key1
key2
key5
key3
key4
{key1=value1, key2=value2, key5=value5, key4=value4}

例外は発生せず、うまく削除できた。Enumerationと比べてIteratorの方が使い勝手がよくなっていることがわかる。



TOP > Java > EnumerationとIteratorの違い

Tweet ̃Gg[͂ĂȃubN}[Nɒlj
技術空間