我有一个返回java.lang.Iterable<T>的接口。
我想使用Java 8流API来操作这个结果。
然而Iterable不能“流”。
任何想法如何使用Iterable作为流而不转换为列表?
我有一个返回java.lang.Iterable<T>的接口。
我想使用Java 8流API来操作这个结果。
然而Iterable不能“流”。
任何想法如何使用Iterable作为流而不转换为列表?
当前回答
你可以很容易地从Iterable或Iterator中创建一个Stream:
public static <T> Stream<T> stream(Iterable<T> iterable) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
iterable.iterator(),
Spliterator.ORDERED
),
false
);
}
其他回答
你可以很容易地从Iterable或Iterator中创建一个Stream:
public static <T> Stream<T> stream(Iterable<T> iterable) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
iterable.iterator(),
Spliterator.ORDERED
),
false
);
}
There's a much better answer than using spliteratorUnknownSize directly, which is both easier and gets a better result. Iterable has a spliterator() method, so you should just use that to get your spliterator. In the worst case, it's the same code (the default implementation uses spliteratorUnknownSize), but in the more common case, where your Iterable is already a collection, you'll get a better spliterator, and therefore better stream performance (maybe even good parallelism). It's also less code:
StreamSupport.stream(iterable.spliterator(), false)
.filter(...)
.moreStreamOps(...);
正如你所看到的,从一个Iterable对象中获取一个流(也请参见这个问题)并不是很痛苦。
所以另一个回答提到,Guava支持使用:
Streams.stream(iterable);
我想强调的是,该实现与其他答案略有不同。如果Iterable类型为Collection,则对其进行强制转换。
public static <T> Stream<T> stream(Iterable<T> iterable) {
return (iterable instanceof Collection)
? ((Collection<T>) iterable).stream()
: StreamSupport.stream(iterable.spliterator(), false);
}
public static <T> Stream<T> stream(Iterator<T> iterator) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(iterator, 0),
false
);
}
我想建议使用JOOL库,它隐藏了Seq.seq(iterable)调用背后的分割器魔法,还提供了一大堆额外的有用功能。
如果你碰巧使用Vavr(以前称为Javaslang),这可以很简单:
Iterable i = //...
Stream.ofAll(i);