使用Java 8 JDK将Iterable转换为Stream
我有一个接口,它返回java.lang.Iterable<T>
。
我想用Java 8 Stream API来处理这个结果。
然而,Iterable不能“stream”。
任何更好的主意如何使用stream(没有将Iterable转换为List)?
有一个比直接使用spliteratorUnknownSize
更好的答案,这是更容易,并得到一个更好的结果。 Iterable
有一个spliterator()
方法,所以你应该使用它来得到你的分割器。 在最糟糕的情况下,它的代码相同(默认实现使用spliteratorUnknownSize
),但在更常见的情况下,如果您的Iterable
已经是一个集合,您将得到一个更好的分割器,因此更好的stream处理性能。)它也less了一些代码:
StreamSupport.stream(iterable.spliterator(), false) .filter(...) .moreStreamOps(...);
正如你所看到的,从Iterable获取stream(请参阅为什么Iterable <T>不提供stream()和parallelStream()方法? )并不是很痛苦。
如果您可以使用番石榴图书馆,从版本21,您可以使用
Streams.stream(iterable)
您可以使用Iterable
或Iterator
轻松创buildStream
:
public static <T> Stream<T> stream(Iterable<T> iterable) { return StreamSupport.stream( Spliterators.spliteratorUnknownSize( iterable.iterator(), Spliterator.ORDERED ), false ); }
我想build议使用JOOL库,它隐藏了Seq.seq(iterable)调用背后的分割魔术,还提供了一大堆其他有用的function。
我创build了这个类:
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)。
这个问题的一个非常简单的解决方法是创build一个扩展Iterable<T>
的Streamable<T>
接口,它包含一个default <T> stream()
方法。
interface Streamable<T> extends Iterable<T> { default Stream<T> stream() { return StreamSupport.stream(spliterator(), false); } }
现在,只要声明它们implements Streamable<T>
而不是Iterable<T>
任何你的Iterable<T>
都可以简单地进行stream传输。
如果您碰巧使用了Vavr(以前称为Javaslang),那么这可以很简单:
Iterable i = //... Stream.ofAll(i);
所以作为另一个答案提到番石榴有这样的支持:
Streams.stream(iterable);
我想强调一下,实现和其他build议略有不同。 如果Iterable
是typesCollection
他们会投它。
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 ); }