可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Is it possible to iterate an Enumeration
by using Lambda Expression? What will be the Lambda representation of the following code snippet:
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
while (nets.hasMoreElements()) {
NetworkInterface networkInterface = nets.nextElement();
}
I didn't find any stream within it.
回答1:
In case you don’t like the fact that Collections.list(Enumeration)
copies the entire contents into a (temporary) list before the iteration starts, you can help yourself out with a simple utility method:
public static <T> void forEachRemaining(Enumeration<T> e, Consumer<? super T> c) {
while(e.hasMoreElements()) c.accept(e.nextElement());
}
Then you can simply do forEachRemaining(enumeration, lambda-expression);
(mind the import static
feature)…
回答2:
(This answer shows one of many options. Just because is has had acceptance mark, doesn't mean it is the best one. I suggest reading other answers and picking one depending on situation you are in. Personally for Java 8 I find Holger's answer nicest because it is also simple but doesn't need additional iteration - which happens in mine solution. But for Java 9 solution visit Tagir Valeev answer)
You can copy elements from your Enumeration
to ArrayList
with Collections.list
and then use it like
Collections.list(yourEnumeration).forEach(yourAction);
回答3:
If there are a lot of Enumerations in your code, I recommend creating a static helper method, that converts an Enumeration into a Stream. The static method might look as follows:
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);
}
Use the method with a static import. In contrast to Holger's solution, you can benefit from the different stream operations, which might make the existing code even simpler. Here is an example:
Map<...> map = enumerationAsStream(enumeration)
.filter(Objects::nonNull)
.collect(groupingBy(...));
回答4:
Since Java-9 there will be new default method Enumeration.asIterator()
which will make pure Java solution simpler:
nets.asIterator().forEachRemaining(iface -> { ... });
回答5:
You can use the following combination of standard functions:
StreamSupport.stream(Spliterators.spliteratorUnknownSize(CollectionUtils.toIterator(enumeration), Spliterator.IMMUTABLE), parallel)
You may also add more characteristics like NONNULL
or DISTINCT
.
After applying static imports this will become more readable:
stream(spliteratorUnknownSize(toIterator(enumeration), IMMUTABLE), false)
now you have a standard Java 8 Stream to be used in any way! You may pass true
for parallel processing.
To convert from Enumeration to Iterator use any of:
CollectionUtils.toIterator()
from Spring 3.2 or you can use
IteratorUtils.asIterator()
from Apache Commons Collections 3.2
Iterators.forEnumeration()
from Google Guava
回答6:
For Java 8 the simplest transformation of enumeration to stream is:
Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
回答7:
I know this is an old question but I wanted to present an alternative to Collections.asList and Stream functionality. Since the question is titled "Iterate an Enumeration", I recognize sometimes you want to use a lambda expression but an enhanced for loop may be preferable as the enumerated object may throw an exception and the for loop is easier to encapsulate in a larger try-catch code segment (lambdas require declared exceptions to be caught within the lambda). To that end, here is using a lambda to create an Iterable which is usable in a for loop and does not preload the enumeration:
/**
* 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();
}
};
}