在Java 8中迭代枚举

时间:2014-04-24 06:51:58

标签: java lambda iteration enumeration java-8

是否可以使用Lambda Expression迭代Enumeration?以下代码片段的Lambda表示形式是什么:

Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();

while (nets.hasMoreElements()) {
    NetworkInterface networkInterface = nets.nextElement();

}

我在其中找不到任何信息流。

7 个答案:

答案 0 :(得分:84)

(这个答案显示了许多选项中的一个。只是因为 有接受标记,并不意味着它是最好的。我建议阅读其他答案并选择一个取决于您所处的情况。就Java 8而言,我发现Holger's answer最好,因为它也很简单,但不需要额外的迭代 - 这在我的解决方案中会发生。但对于Java 9解决方案,请访问Tagir Valeev answer


您可以使用Enumeration将元素从ArrayList复制到Collections.list,然后再使用

Collections.list(yourEnumeration).forEach(yourAction);

答案 1 :(得分:50)

如果代码中有很多 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);
}

将此方法与静态导入一起使用。与Holger的解决方案相比,您可以从不同的操作中受益,这可能使现有代码更简单。这是一个例子:

Map<...> map = enumerationAsStream(enumeration)
    .filter(Objects::nonNull)
    .collect(groupingBy(...));

答案 2 :(得分:45)

由于Java-9将有新的默认方法Enumeration.asIterator(),这将使纯Java解决方案更简单:

nets.asIterator().forEachRemaining(iface -> { ... });

答案 3 :(得分:33)

如果您不喜欢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功能)...

答案 4 :(得分:11)

您可以使用以下标准功能组合:

StreamSupport.stream(Spliterators.spliteratorUnknownSize(CollectionUtils.toIterator(enumeration), Spliterator.IMMUTABLE), parallel)

您还可以添加更多特征,例如NONNULLDISTINCT

应用静态导入后,这将变得更具可读性:

stream(spliteratorUnknownSize(toIterator(enumeration), IMMUTABLE), false)

现在您可以以任何方式使用标准Java 8 Stream!您可以通过true进行并行处理。

要从Enumeration转换为Iterator,请使用以下任意一个:

    来自Spring 3.2的
  • CollectionUtils.toIterator()或者您可以使用
  • 来自Apache Commons Collections 3.2的
  • IteratorUtils.asIterator()
  • 来自Google Guava的
  • Iterators.forEnumeration()

答案 5 :(得分:5)

对于Java 8,枚举到流的最简单的转换是:

Collections.list(NetworkInterface.getNetworkInterfaces()).stream()

答案 6 :(得分:4)

我知道这是一个老问题,但我想提供Collections.asList和Stream功能的替代方案。由于问题标题为“迭代枚举”,我有时会认识到你想使用lambda表达式,但是增强的for循环可能更好,因为枚举对象可能抛出异常并且for循环更容易封装在更大的try-中catch代码段(lambdas要求在lambda中捕获声明的异常)。为此,这里使用lambda创建一个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();
        }
    };
}