Lambda Expressionを使用してEnumeration
を反復処理することはできますか?次のコードスニペットのLambda表現はどうなりますか?
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
while (nets.hasMoreElements()) {
NetworkInterface networkInterface = nets.nextElement();
}
ストリームが見つかりませんでした。
Collections.list(Enumeration)
がイテレーションが始まる前にコンテンツ全体を(一時的な)リストにコピーするという事実が気に入らない場合は、簡単なユーティリティメソッドを使用して手伝うことができます。
_public static <T> void forEachRemaining(Enumeration<T> e, Consumer<? super T> c) {
while(e.hasMoreElements()) c.accept(e.nextElement());
}
_
その後、単にforEachRemaining(enumeration, lambda-expression);
を実行できます(_import static
_機能に注意してください)…
(この答えは、多くのオプションの1つを示しています。 持っている 受け入れマークがあった、それが最高のものであることを意味するものではありません。他の答えを読んで、あなたがいる状況に応じて答えを選ぶことをお勧めします。IMO:
-for Java 8 Holger's answer が最も優れています。シンプルであるだけでなく、鉱山ソリューションで発生する追加の反復を必要としないためです。
-for Java 9私は Tagir Valeev answer )から解決策を選択します
Enumeration
の要素を ArrayList
に Collections.list
でコピーして使用できます好む
Collections.list(yourEnumeration).forEach(yourAction);
コードに多くのEnumerationsがある場合、EnumerationをStreamに変換する静的ヘルパーメソッドを作成することをお勧めします。静的メソッドは次のようになります。
public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
new Iterator<T>() {
public T next() {
return e.nextElement();
}
public boolean hasNext() {
return e.hasMoreElements();
}
},
Spliterator.ORDERED), false);
}
static importでメソッドを使用します。 Holgerのソリューションとは対照的に、さまざまなstream操作の恩恵を受けることができます。これにより、既存のコードがさらに簡単になります。以下に例を示します。
Map<...> map = enumerationAsStream(enumeration)
.filter(Objects::nonNull)
.collect(groupingBy(...));
Java-9以降、新しいデフォルトメソッド Enumeration.asIterator()
が追加され、純粋なJavaソリューションがより簡単になります。
nets.asIterator().forEachRemaining(iface -> { ... });
次の標準機能の組み合わせを使用できます。
_StreamSupport.stream(Spliterators.spliteratorUnknownSize(CollectionUtils.toIterator(enumeration), Spliterator.IMMUTABLE), parallel)
_
NONNULL
やDISTINCT
などの特性を追加することもできます。
静的インポートを適用すると、これはさらに読みやすくなります。
_stream(spliteratorUnknownSize(toIterator(enumeration), IMMUTABLE), false)
_
これで、標準のJava 8ストリームを任意の方法で使用できます!並列処理にtrue
を渡すことができます。
列挙型からイテレータに変換するには、次のいずれかを使用します。
CollectionUtils.toIterator()
Spring 3.2から、または使用できますIteratorUtils.asIterator()
Apache Commons Collections 3.2からIterators.forEnumeration()
Google GuavaからJava 8の場合、列挙からストリームへの最も単純な変換は次のとおりです。
Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
これは古い質問であることは知っていますが、Collections.asListおよびStream機能の代替を提示したかったのです。質問のタイトルは「列挙の反復」であるため、ラムダ式を使用したい場合があることを認識していますが、列挙オブジェクトが例外をスローし、forループがより大きなtry-コードセグメントをキャッチします(ラムダでは、宣言された例外をラムダ内でキャッチする必要があります)。そのために、ここではラムダを使用してforループで使用可能で列挙をプリロードしないIterableを作成しています。
/**
* Creates lazy Iterable for Enumeration
*
* @param <T> Class being iterated
* @param e Enumeration as base for Iterator
* @return Iterable wrapping Enumeration
*/
public static <T> Iterable<T> enumerationIterable(Enumeration<T> e)
{
return () -> new Iterator<T>()
{
@Override
public T next()
{
return e.nextElement();
}
@Override
public boolean hasNext()
{
return e.hasMoreElements();
}
};
}