如何将Java枚举转换为流?

如何将Java枚举转换为流?,java,java-8,java-stream,Java,Java 8,Java Stream,我有一个第三方库,它为我提供了一个枚举。我希望将该枚举作为Java8流,在其上调用过滤器、映射和平面映射 现有的图书馆里有这个吗?我已经在引用Guava和ApacheCommons,所以如果它们中的任何一个都有理想的解决方案的话 或者,将枚举转化为流的最佳/最简单的方法是什么,同时保留所有事物的惰性?已经提供了一种解决方案,可以从枚举中创建流: 然而,上面的代码是“使用迭代器的受害者,因为它是如此熟悉”的反模式。创建的迭代器将封装到新拆分器接口的实现中,与直接实现拆分器相比没有任何优势: pub

我有一个第三方库,它为我提供了一个
枚举
。我希望将该枚举作为Java8
,在其上调用
过滤器
映射
平面映射

现有的图书馆里有这个吗?我已经在引用Guava和ApacheCommons,所以如果它们中的任何一个都有理想的解决方案的话

或者,将
枚举
转化为
的最佳/最简单的方法是什么,同时保留所有事物的惰性?

已经提供了一种解决方案,可以从
枚举
中创建

然而,上面的代码是“使用<代码>迭代器的受害者,因为它是如此熟悉”的反模式。创建的
迭代器
将封装到新
拆分器
接口的实现中,与直接实现
拆分器
相比没有任何优势:

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);
}
公共静态流枚举ASSTREAM(枚举e){
returnstreamsupport.stream(
新拆分器。抽象拆分器(Long.MAX_值,拆分器。有序){
public boolean tryAdvance(Consumer根据,您可以使用
迭代器。forEnumeration()
方法:

Enumeration<Something> enumeration = ...;

Iterator<SomeThing> iterator = Iterators.forEnumeration(enumeration);
枚举=。。。;
迭代器迭代器=迭代器。forEnumeration(枚举);
在中,解释了如何从迭代器获取流:

Stream<Something> stream = StreamSupport.stream(
    Spliterators.spliteratorUnknownSize(
        iterator, Spliterator.ORDERED),
    false);
Stream=StreamSupport.Stream(
拆分器。拆分器未知(
迭代器,拆分器。有序),
假);

在Java 9中,可以使用一行程序将
枚举
转换为

Enumeration<String> en = ... ;
Stream<String> str = StreamSupport.stream(
    Spliterators.spliteratorUnknownSize(en.asIterator(), Spliterator.ORDERED),
    false
);
枚举en=; Stream str=StreamSupport.Stream( Spliterators.spliteratorUnknownSize(en.asIterator(),Spliterator.ORDERED), 假的 );
(嗯,这是一条相当长的队伍。)

如果您不使用Java 9,则可以使用中给出的技术手动将
枚举
转换为
迭代器

在我的库中,有一个简单的方法可以完成此任务:

Stream<String> stream = StreamEx.of(enumeration);
Stream=streamx.of(枚举);

请注意,它不仅是@Holger解决方案的快捷方式,而且以不同的方式实现。特别是,与涉及拆分器的解决方案相比,它具有显著更好的并行执行特性。拆分器未知化()

为什么不使用vanilla Java:

Collections.list(enumeration).stream()...

然而,正如@MicahZoltu所提到的,必须考虑枚举中的项数,因为
集合。list
将首先迭代枚举,以复制
ArrayList
中的元素。从那里可以使用常规的
方法。而这对于许多集合流来说是常见的但是,如果枚举太大(如无限),这可能会导致问题,因为枚举必须在列表中转换,那么应该使用此处描述的其他方法。

相关:链接的问题是如何将
枚举
(Java 1.0)转换为
迭代器
(Java 1.2).我在问如何将其转换为
(Java 1.8)。虽然链接问题中的最后一个答案似乎回答了这个问题,但该答案对于所问的问题来说是错误的。应该在此处提供该答案,以便将来的搜索者能够成功找到该答案。也许@ArneBurmeister希望将答案复制到此处,以便直接回答该问题?重新作为的答案打开链接问题不讨论懒惰行为,也不是发布创建
流的替代方法的正确位置(因为这不是链接问题的范围)。虽然在这种情况下它可能会起作用,但iterable并不是一个真正的iterable:你可以只迭代它一次!@dfogni流也会发生同样的情况。使用和放弃,他们说:)在上下文中,它是完全正常的,但它是一个等待发生的bug,因为它声明的对象的语义与其接口所说的不同。更重要的是,它是对Iterable接口的滥用,Iterable接口碰巧可以从lambda分配,但不应该是@FunctionInterface。我们几乎可以将所有内容都设置为一行,如果我们让这行足够长;^)这将枚举整个
枚举
,使其成为一个列表,然后为您提供对列表的流访问。如果枚举很小,这可能是一种合理的方法。如果枚举非常大,这可能是一个昂贵且不必要的操作。如果枚举是无限的,这将使您的应用程序崩溃。@Mica这是一个需要考虑的问题。我会更新答案。感谢霍格尔。使用SpRealActudio的优点是什么?这里命令与其他值不同。@ ICEDANTE <代码>命令意味着有一个定义的相遇顺序,因此它意味着在假设D的情况下,不允许流实现进行优化。ata是无序的。因为对于未知的
枚举
,我们不知道顺序是否有意义,我们必须假设它可能有意义并指定此特征。调用方仍然可以调用
无序()
当他们知道顺序与特定数据无关时,可以在流上进行优化。但我们的初始前提必须是顺序可能很重要。请注意,自java 9以来,就有了
枚举35; asIterator()
Stream<String> stream = StreamEx.of(enumeration);
Collections.list(enumeration).stream()...