使用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) 

您可以使用IterableIterator轻松创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 ); }