在Java 8中,我们有类Stream<T>,它奇怪地有一个方法
Iterator<T> iterator()
所以你会期望它实现接口Iterable<T>,这需要这个方法,但事实并非如此。
当我想使用foreach循环遍历一个流时,我必须做如下的事情
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)) { ... }
我是不是遗漏了什么?
kennytm描述了为什么将Stream作为Iterable是不安全的,Zhong Yu提供了一个变通方案,允许将Stream作为Iterable使用,尽管是以一种不安全的方式。有可能两全其美:来自流的可重用Iterable,满足Iterable规范的所有保证。
注意:SomeType在这里不是类型参数——您需要用合适的类型(例如,String)替换它,或者使用反射
Stream<SomeType> stream = ...;
Iterable<SomeType> iterable = stream.collect(toList()):
它有一个主要的缺点:
惰性迭代的好处将会丧失。如果您计划立即遍历当前线程中的所有值,那么任何开销都可以忽略不计。但是,如果您计划只进行部分迭代或在不同的线程中进行迭代,那么这种立即的完整迭代可能会产生意想不到的后果。
当然,最大的优点是可以重用Iterable,而(Iterable<SomeType>) stream::iterator只允许一次使用。如果接收代码将在集合上迭代多次,这不仅是必要的,而且可能有利于性能。
kennytm描述了为什么将Stream作为Iterable是不安全的,Zhong Yu提供了一个变通方案,允许将Stream作为Iterable使用,尽管是以一种不安全的方式。有可能两全其美:来自流的可重用Iterable,满足Iterable规范的所有保证。
注意:SomeType在这里不是类型参数——您需要用合适的类型(例如,String)替换它,或者使用反射
Stream<SomeType> stream = ...;
Iterable<SomeType> iterable = stream.collect(toList()):
它有一个主要的缺点:
惰性迭代的好处将会丧失。如果您计划立即遍历当前线程中的所有值,那么任何开销都可以忽略不计。但是,如果您计划只进行部分迭代或在不同的线程中进行迭代,那么这种立即的完整迭代可能会产生意想不到的后果。
当然,最大的优点是可以重用Iterable,而(Iterable<SomeType>) stream::iterator只允许一次使用。如果接收代码将在集合上迭代多次,这不仅是必要的,而且可能有利于性能。