web-dev-qa-db-ja.com

なぜforeachをJava列挙で使用できないのですか?

なぜできないのですか:

Enumeration e = ...
for (Object o : e)
  ...
66
ripper234

Enumeration<T>Iterable<T> を拡張しないためです。 反復可能な列挙を作成する例 です。

なぜそれが興味深い質問なのかについて。これはまさにあなたの質問ではありませんが、いくつかの光を当てています。 Java Collections API Design FAQ から:

イテレータが列挙を拡張しないのはなぜですか?

列挙型のメソッド名は不幸だと考えています。それらは非常に長く、非常に頻繁に使用されます。メソッドを追加してまったく新しいフレームワークを作成していることを考えると、名前を改善する機会を利用しないのは愚かなことだと感じました。もちろん、イテレータで新しい名前と古い名前をサポートすることもできますが、それは価値がないようです。

これは基本的に、Sunが非常に冗長な構文を持つ非常に初期のJavaである列挙から距離を置きたいことを示唆しています。

60
cletus

コレクションユーティリティクラスを使用して、列挙を次のように反復可能にすることができます。

Enumeration headerValues=request.getHeaders("mycustomheader");
List headerValuesList=Collections.list(headerValues);

for(Object headerValueObj:headerValuesList){
 ... do whatever you want to do with headerValueObj
}
40
user1555669

この問題は、Enumeration用とIterator用の2つの非常に単純なクラスで解決しました。列挙ラッパーは次のとおりです。

static class IterableEnumeration<T>
extends Object
implements Iterable<T>, Iterator<T>
{
private final Enumeration<T>        enumeration;
private boolean                     used=false;

IterableEnumeration(final Enumeration<T> enm) {
    enumeration=enm;
    }

public Iterator<T> iterator() {
    if(used) { throw new IllegalStateException("Cannot use iterator from asIterable wrapper more than once"); }
    used=true;
    return this;
    }

public boolean hasNext() { return enumeration.hasMoreElements(); }
public T       next()    { return enumeration.nextElement();     }
public void    remove()  { throw new UnsupportedOperationException("Cannot remove elements from AsIterator wrapper around Enumeration"); }
}

静的ユーティリティメソッド(これは私の好みです)で使用できます:

/**
 * Convert an `Enumeration<T>` to an `Iterable<T>` for a once-off use in an enhanced for loop.
 */
static public <T> Iterable<T> asIterable(final Enumeration<T> enm) {
    return new IterableEnumeration<T>(enm);
    }

...

for(String val: Util.asIterable(enm)) {
    ...
    }

またはクラスをインスタンス化することにより:

for(String val: new IterableEnumeration<String>(enm)) {
    ...
    }
6
Lawrence Dol

新しいスタイルのforループ( "foreach")は、配列、およびIterableインターフェイスを実装するもので機能します。

また、IteratorよりもIterableに類似しているため、Enumerationもそうでない限り、Iteratorがforeachで機能することは意味がありません(そうでない場合) 。 EnumerationIteratorを支持して推奨されません。

3

Java 8以降では、これが可能です。

import Java.util.Collections;
import Java.util.Enumeration;

Enumeration e = ...;
Collections.list(e).forEach(o -> {
    ... // use item "o"
});
1
slartidan

EnumerationIterableを実装していないため、foreachループで直接使用することはできません。ただし、 Apache Commons Collections を使用すると、列挙を次のように繰り返すことができます。

_for (Object o : new IteratorIterable(new EnumerationIterator(e))) {
    ...
}
_

Collections.list()を使用して短い構文を使用することもできますが、これは効率的ではありません(要素に対する2回の反復とより多くのメモリ使用量)。

_for (Object o : Collections.list(e))) {
    ...
}
_
1
Emmanuel Bourg

列挙(およびこのインターフェイスから派生したほとんどのクラス)はIterableを実装しないためです。

独自のラッパークラスを記述してみてください。

0
Stroboskop