如何将Java枚举转换为流? [英] How do I turn a Java Enumeration into a Stream?

查看:89
本文介绍了如何将Java枚举转换为流?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个第三方库,它给了我一个 Enumeration< String> 。我希望懒惰地使用该枚举作为Java 8 Stream ,调用类似 filter map flatMap 就可以了。

I have a third party library that gives me an Enumeration<String>. I want to work with that enumeration lazily as a Java 8 Stream, calling things like filter, map and flatMap on it.

是否有现有的库具有此功能在里面?我已经引用了Guava和Apache Commons,所以如果其中任何一个都有理想的解决方案。

Is there an existing library that has this in it? I am already referencing Guava and Apache Commons so if either of those have the solution that would be ideal.

或者,什么是最好/最简单的方法来转换 Enumeration 进入 Stream ,同时保留所有内容的懒惰性质?

Alternatively, what is the best/easiest way to turn an Enumeration into a Stream while retaining the lazy nature of everything?

推荐答案

此答案已经提供了一个创建的解决方案流枚举

This answer already provides a solution which creates a Stream out of an 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);
 }


应该强调的是结果 与任何其他一样懒,因为它不会处理之前的任何项目终端操作已经开始,如果终端操作是短路的,它将只根据需要迭代尽可能多的项目。

It should be emphasized that the resulting Stream is as lazy as any other Stream, as it won’t process any items before the terminal action has been commenced and if the terminal operation is short-circuiting, it will iterate only as many items as necessary.

尽管如此,它还有改进的余地。当有一种直接处理所有元素的方法时,我总是会添加 forEachRemaining 方法。对于大多数非短路操作,所述方法将由 Stream 实现调用:

Still, it has room for improvement. I’d always add a forEachRemaining method when there is a straight-forward way to process all elements. Said method will be called by the Stream implementation for most non-short-circuiting operations:

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

但是,上面的代码是使用<$ c $的受害者c>迭代器因为它是如此熟悉的模式。创建的 Iterator 将被包装到新的 Spliterator 接口的实现中,并没有优于实现 Spliterator 直接:

However, the code above is a victim of the "using Iterator because it’s so familiar" pattern. The created Iterator will get wrapped into an implementation of the new Spliterator interface and provides no advantage over implementing Spliterator directly:

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

在源代码级别,此实现就像<$ c一样简单$ c> Iterator -based,但取消了从 Spliterator Iterator 的委派。它只需要读者了解新的API ......

On the source code level, this implementation is as simple as the Iterator-based, but eliminates the delegation from a Spliterator to an Iterator. It only requires its readers to learn about the new API…

这篇关于如何将Java枚举转换为流?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆