小编典典

如何将Java枚举转换为流?

java

我有一个第三方图书馆给我一个图书馆Enumeration<String>。我想像Java
8那样懒惰地使用该枚举,并Stream调用诸如此类的东西。filter``map``flatMap

有没有现成的图书馆?我已经在引用Guava和Apache Commons,所以如果其中任何一个都有理想的解决方案。

另外,在保留所有内容的懒惰性质的同时将Enumerationa 变成最佳/最简单的方法Stream是什么?


阅读 410

收藏
2020-12-03

共1个答案

小编典典

这个答案已经提供了一个解决方案,可以解决Stream以下问题Enumeration

 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);
 }

应当强调的是,由此而来Stream
懒任何其他Stream的,因为它不会处理任何物品的终端动作已经开始之前,如果终端操作是短路,它会遍历只有尽可能多的项目是必要的。

尽管如此,它仍有改进的空间。forEachRemaining当有一种直接处理所有元素的方法时,我总是会添加一个方法。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();
                }
                public void forEachRemaining(Consumer<? super T> action) {
                    while(e.hasMoreElements()) action.accept(e.nextElement());
                }
            },
            Spliterator.ORDERED), false);
}

但是,上面的代码是“使用,Iterator因为它非常熟悉”反模式的受害者。创建的Iterator将被包装到新Spliterator接口的实现中,与Spliterator直接实现相比,没有任何优势:

public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
    return StreamSupport.stream(
        new Spliterators.AbstractSpliterator<T>(Long.MAX_VALUE, Spliterator.ORDERED) {
            public boolean tryAdvance(Consumer<? super T> action) {
                if(e.hasMoreElements()) {
                    action.accept(e.nextElement());
                    return true;
                }
                return false;
            }
            public void forEachRemaining(Consumer<? super T> action) {
                while(e.hasMoreElements()) action.accept(e.nextElement());
            }
    }, false);
}

在源代码级别上,此实现与Iterator基于-
一样简单,但是消除了从Spliterator到的委派Iterator。它仅要求其读者学习新的API。

2020-12-03