是否可以Enumeration
使用Lambda表达式进行迭代?以下代码段的Lambda表示形式是什么:
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
while (nets.hasMoreElements()) {
NetworkInterface networkInterface = nets.nextElement();
}
我没有在其中找到任何信息流。
是否可以Enumeration
使用Lambda表达式进行迭代?以下代码段的Lambda表示形式是什么:
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
while (nets.hasMoreElements()) {
NetworkInterface networkInterface = nets.nextElement();
}
我没有在其中找到任何信息流。
Answers:
如果您不喜欢在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
功能)…
(此答案显示了许多选项之一。仅仅是因为它具有接受标记,并不意味着它是最佳选择。我建议阅读其他答案,然后根据您所处的情况选择一个答案。IMO:
-对于Java 8 Holger的答案最好,因为除了简单之外,它不需要在矿井解决方案中进行额外的迭代
-对于Java 9,我将从Tagir Valeev选择解决方案answer)
您可以将元素从中复制Enumeration
到ArrayList
,Collections.list
然后像
Collections.list(yourEnumeration).forEach(yourAction);
Enum
但问题是关于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);
}
与静态导入一起使用该方法。与Holger的解决方案相比,您可以从不同的流操作中受益,这可能会使现有代码更加简单。这是一个例子:
Map<...> map = enumerationAsStream(enumeration)
.filter(Objects::nonNull)
.collect(groupingBy(...));
list.forEach(…)
和list.stream(). ⟨stream ops⟩ .forEach(…)
。
public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) { return Collections.list(e).stream(); }
会做同样的事情,但是要简单得多。
从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 Stream!您可以通过true
并行处理。
要将枚举转换为迭代器,请使用以下任一方法:
CollectionUtils.toIterator()
从Spring 3.2开始,或者您可以使用IteratorUtils.asIterator()
来自Apache Commons Collections 3.2Iterators.forEnumeration()
来自Google Guavaorg.apache.commons.collections.CollectionUtils
。
对于Java 8,枚举到流的最简单转换是:
Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
我知道这是一个老问题,但是我想提出Collections.asList和Stream功能的替代方法。由于问题的标题为“迭代枚举”,因此我认识到有时您想使用lambda表达式,但最好使用增强的for循环,因为枚举的对象可能会引发异常,并且for循环更容易封装在较大的try-中。捕获代码段(lambda需要在lambda中捕获声明的异常)。为此,这里使用lambda创建一个Iterable,该Iterable可在for循环中使用,并且不会预加载枚举:
/**
* 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();
}
};
}