我有一个返回java.lang.Iterable<T>
的接口。
我想使用Java 8 Stream API来操作该结果。
但是Iterable不能“流”。
知道如何将Iterable用作Stream而不将其转换为List吗?
答案 0 :(得分:508)
与直接使用spliteratorUnknownSize
相比,这是一个更好的答案,这既容易又获得更好的结果。 Iterable
有一个spliterator()
方法,因此您应该使用它来获取分词符。在最糟糕的情况下,它是相同的代码(默认实现使用spliteratorUnknownSize
),但在更常见的情况下,您的Iterable
已经是一个集合,您将获得一个更好的分裂器,因此更好的流性能(甚至可能是良好的并行性)。它的代码也少了:
StreamSupport.stream(iterable.spliterator(), false)
.filter(...)
.moreStreamOps(...);
正如您所看到的,从Iterable
获取流(另请参阅this question)并不是很痛苦。
答案 1 :(得分:56)
如果您可以使用Guava库,那么从版本21开始,您可以使用
Streams.stream(iterable)
答案 2 :(得分:22)
您可以轻松地从Stream
或Iterable
创建Iterator
:
public static <T> Stream<T> stream(Iterable<T> iterable) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
iterable.iterator(),
Spliterator.ORDERED
),
false
);
}
答案 3 :(得分:9)
我想建议使用JOOL库,它隐藏了Seq.seq(可迭代)调用背后的分裂器魔法,并提供了一大堆额外的有用功能。
答案 4 :(得分:3)
我创建了这个类:
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)。
答案 5 :(得分:3)
解决此问题的一个非常简单的方法是创建一个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>
,您的任何@Transactional
都可以轻松制作流媒体。
答案 6 :(得分:3)
因此,另一个答案提到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
);
}
答案 7 :(得分:0)
如果你碰巧使用Vavr(以前称为Javaslang),这可以很简单:
Iterable i = //...
Stream.ofAll(i);
答案 8 :(得分:-2)
使用Java 8并且没有外部库的另一种方法:
Stream.concat(collectionA.stream(), collectionB.stream())
.collect(Collectors.toList())