roi*_*oim 254 java iterable java-8 java-stream
在Java 8中,我们有Stream <T>类,它奇怪地有一个方法
Iterator<T> iterator()
Run Code Online (Sandbox Code Playgroud)
所以你会期望它实现接口Iterable <T>,这需要完全这个方法,但事实并非如此.
当我想使用foreach循环遍历Stream时,我必须做类似的事情
public static Iterable<T> getIterable(Stream<T> s) {
return new Iterable<T> {
@Override
public Iterator<T> iterator() {
return s.iterator();
}
};
}
for (T element : getIterable(s)) { ... }
Run Code Online (Sandbox Code Playgroud)
我在这里错过了什么吗?
ken*_*ytm 189
已经有人在邮件列表上问过同样的问题 ☺.主要原因是Iterable也有一个可重复的语义,而Stream则没有.
我认为主要原因是它
Iterable
意味着可重用性,而Stream
只能使用一次 - 更像是一种Iterator
.如果
Stream
扩展了,Iterable
那么现有的代码在收到第二次Iterable
抛出的时候可能会感到惊讶.Exception
for (element : iterable)
Zho*_*gYu 153
要转换Stream
到Iterable
,你可以做
Stream<X> stream = null;
Iterable<X> iterable = stream::iterator
Run Code Online (Sandbox Code Playgroud)
要传递Stream
给期望的方法Iterable
,
void foo(Iterable<X> iterable)
Run Code Online (Sandbox Code Playgroud)
只是
foo(stream::iterator)
Run Code Online (Sandbox Code Playgroud)
但它可能看起来很有趣; 更明确一点可能会更好
foo( (Iterable<X>)stream::iterator );
Run Code Online (Sandbox Code Playgroud)
kennytm描述了为什么将a Stream
作为一种处理是不安全的Iterable
,而钟宇提供了一种允许使用Stream
as 的解决方法Iterable
,尽管是以不安全的方式.这是有可能得到两全其美:可再用Iterable
从Stream
满足所做出的一切保障Iterable
规范.
注意:SomeType
这里不是类型参数 - 您需要用适当的类型(例如String
)替换它或使用反射
Stream<SomeType> stream = ...;
Iterable<SomeType> iterable = stream.collect(toList()):
Run Code Online (Sandbox Code Playgroud)
有一个主要缺点:
延迟迭代的好处将会丢失.如果您计划立即迭代当前线程中的所有值,则任何开销都可以忽略不计.但是,如果您计划仅部分迭代或在不同的线程中进行迭代,则此即时且完整的迭代可能会产生意想不到的后果.
当然,最大的优点是你可以重复使用Iterable
,而(Iterable<SomeType>) stream::iterator
只允许一次使用.如果接收代码将多次遍历集合,则这不仅是必要的,而且可能有益于性能.
您可以在for
循环中使用流,如下所示:
Stream<T> stream = ...;
for (T x : (Iterable<T>) stream::iterator) {
...
}
Run Code Online (Sandbox Code Playgroud)
(这使用Java 8功能接口强制转换。)
(这在上面的一些评论中得到了介绍(例如Aleksandr Dubinsky,但是我想将其提出来以使其更清晰可见)。
归档时间: |
|
查看次数: |
34313 次 |
最近记录: |