如何将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()...