迭代Java 8中的枚举


73

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

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

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

}

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


7
枚举在1998年用Java 1.2中的Iterators代替。不幸的是,您仍然必须使用它。:|
彼得·劳瑞

1
:你能适应你的枚举迭代器stackoverflow.com/questions/5007082/...
marcinj

7
@PeterLawrey Iterator出现了,但是仍然有一些使用枚举的核心API。泛型出现了,但是仍然有使用裸类型或返回Object的核心API。Lambdas出现了,但是Swing仍然充满了多方法接口,因此我们不能使用它们。当我发现Java忘记进行现代化的API时,这并没有让我感到惊讶。这让我很伤心。
Trejkaz 2014年

3
@Trejkaz是的,Swing仍然使用Vector和Hashtable。
彼得·劳瑞

@PeterLawrey Servlet API仍使用枚举。
OrangeDog '18 -10-30

Answers:


36

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


87

(此答案显示了许多选项之一。仅仅是因为它具有接受标记,并不意味着它是最佳选择。我建议阅读其他答案,然后根据您所处的情况选择一个答案。IMO:
-对于Java 8 Holger的答案最好,因为除了简单之外,它不需要在矿井解决方案中进行额外的迭代
-对于Java 9,我将从Tagir Valeev选择解决方案answer


您可以将元素从中复制EnumerationArrayListCollections.list然后像

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

16
要注意的是,现在您必须将所有元素存储在列表中。如果很小,那可能很好。但是值得一提,因为有时它太大了而无法容纳在内存中。
Trejkaz 2014年

java.util.stream.Stream#of(yourEnumeration.values())。forEach()怎么样?
Filip

3
@Filip您的评论是关于,Enum但问题是关于Enumeration
Pshemo '16

51

如果您的代码中有很多枚举,建议您创建一个静态帮助器方法,该方法将枚举转换为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(…)
Holger 2014年

1
这不是JDK的一部分吗?
尼克

public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) { return Collections.list(e).stream(); }会做同样的事情,但是要简单得多。
Thomas Fritsch '18

@ThomasFritsch的提议为列表创建了中间副本,这是可以避免的。
克莱里斯-cautiouslyoptimistic-


11

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

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

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

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

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

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

要将枚举转换为迭代器,请使用以下任一方法:

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

1
CollectionUtils来自哪里?似乎不在JDK中。
马丁

@马丁,似乎是org.apache.commons.collections.CollectionUtils
Vadzim 2015年

@Vadzim我检查了Apache Commons Collections 1.0、2.0、2.1.1、3.2.1和4.0,但没有名为CollectionUtils的类包含名为toIterator的方法。
马丁

抱歉,感到困惑,是从3.2春季获得的
Arne Burmeister 2015年


4

我知道这是一个老问题,但是我想提出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();
        }
    };
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.