Mic*_*ltu 56 java java-8 java-stream
我有一个第三方图书馆给了我一个Enumeration<String>.我想懒洋洋地与枚举工作作为Java 8 Stream,呼叫之类的东西filter,map并flatMap在其上.
是否有现有的库?我已经引用了Guava和Apache Commons,所以如果其中任何一个都有理想的解决方案.
或者,是什么把一个最好/最简单的方式Enumeration进入Stream,同时保留所有的懒惰天性?
Bri*_*ice 100
为什么不使用vanilla Java:
Collections.list(enumeration).stream()...
Run Code Online (Sandbox Code Playgroud)
但是,正如@MicahZoltu所提到的,枚举中的项目数必须被考虑在内,因为Collections.list它将首先遍历枚举以复制元素中的元素ArrayList.从那里stream可以使用常规方法.虽然这对于许多集合流操作来说是常见的,但如果枚举太大(如无限),这可能会导致问题,因为枚举必须在列表中进行转换,然后应该使用此处描述的其他方法.
Hol*_*ger 41
这个答案已经提供了一个解决方案,可以创建Stream一个Enumeration:
Run Code Online (Sandbox Code Playgroud)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);
}
Run Code Online (Sandbox Code Playgroud)
但是,上面的代码是"使用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);
}
Run Code Online (Sandbox Code Playgroud)
在源代码级别,这个实现就像Iterator基于-based 一样简单,但是消除了从a Spliterator到a的委托Iterator.它只需要读者了解新的API ...
Stu*_*rks 26
在Java 9中,可以使用单行转换Enumeration为a Stream:
Enumeration<String> en = ... ;
Stream<String> str = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(en.asIterator(), Spliterator.ORDERED),
false
);
Run Code Online (Sandbox Code Playgroud)
(嗯,这是一个相当长的路线.)
如果您不使用Java 9,则可以使用Holger答案中给出的技术将其Enumeration转换为Iterator手动.
根据Guava文档,您可以使用以下Iterators.forEnumeration()方法:
Enumeration<Something> enumeration = ...;
Iterator<SomeThing> iterator = Iterators.forEnumeration(enumeration);
Run Code Online (Sandbox Code Playgroud)
在这个问题中,它解释了如何从迭代器获取流:
Stream<Something> stream = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
iterator, Spliterator.ORDERED),
false);
Run Code Online (Sandbox Code Playgroud)
在我的StreamEx库中,有一个简单的方法StreamEx.of(Enumeration)可以完成这项工作:
Stream<String> stream = StreamEx.of(enumeration);
Run Code Online (Sandbox Code Playgroud)
请注意,它不仅仅是@Holger 解决方案的快捷方式,而是以不同的方式实现的。特别是,与涉及Spliterators.spliteratorUnknownSize().
| 归档时间: |
|
| 查看次数: |
23260 次 |
| 最近记录: |