我有一个返回java.lang.Iterable<T>的接口。
java.lang.Iterable<T>
我想使用Java 8流API来操作这个结果。
然而Iterable不能“流”。
任何想法如何使用Iterable作为流而不转换为列表?
你可以很容易地从Iterable或Iterator中创建Stream:
Iterable
Iterator
Stream
public static <T> Stream<T> stream(Iterable<T> iterable) { return StreamSupport.stream( Spliterators.spliteratorUnknownSize( iterable.iterator(), Spliterator.ORDERED ), false ); }
有一个比直接使用spliteratorUnknownSize更好的答案,后者既更简单,也能得到更好的结果。Iterable有一个spliterator()方法,所以你应该使用它来获取你的分离器。在最坏的情况下,它是相同的代码(默认实现使用spliteratorUnknownSize),但在更常见的情况下,你的Iterable已经是一个集合,你会得到一个更好的分割器,因此更好的流性能(甚至可能是良好的并行性)。它的代码也更少:
spliteratorUnknownSize
spliterator()
StreamSupport.stream(iterable.spliterator(), false) .filter(...) .moreStreamOps(...);
正如你所看到的,从Iterable(另见这个问题)中获取流不是很痛苦。
我建议使用JOOL库,它隐藏了Seq.seq(iterable)调用背后的分割器魔法,还提供了一大堆额外的有用功能。
Seq.seq(iterable)
我创建了这个类:
public class Streams { /** * Converts Iterable to stream */ public static <T> Stream<T> streamOf(final Iterable<T> iterable) { return toStream(iterable, false); } /** * Converts Iterable to parallel stream */ public static <T> Stream<T> parallelStreamOf(final Iterable<T> iterable) { return toStream(iterable, true); } private static <T> Stream<T> toStream(final Iterable<T> iterable, final boolean isParallel) { return StreamSupport.stream(iterable.spliterator(), isParallel); } }
我认为它是完全可读的,因为您不必考虑分裂器和布尔值(isParallel)。
如果你可以使用番石榴库,自版本21起,你就可以使用
Streams.stream(iterable)
解决这个问题的一个非常简单的方法是创建一个Streamable<T>接口,扩展Iterable<T>,其中包含一个default <T> stream()方法。
Streamable<T>
Iterable<T>
default <T> stream()
interface Streamable<T> extends Iterable<T> { default Stream<T> stream() { return StreamSupport.stream(spliterator(), false); } }
现在你的任何Iterable<T>都可以通过声明为implements Streamable<T>而不是Iterable<T>来简单地变成可流的。
implements Streamable<T>
如果你碰巧使用Vavr(以前称为Javaslang),这可以很简单:
Iterable i = //... Stream.ofAll(i);
所以另一个回答提到,Guava支持使用:
Streams.stream(iterable);
我想强调的是,该实现与其他答案略有不同。如果Iterable类型为Collection,则转换它。
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 ); }