I have an interface which returns java.lang.Iterable<T>
.
我有一个返回java.lang.Iterable
I would like to manipulate that result using the Java 8 Stream API.
我想使用Java 8流API来操作这个结果。
However Iterable can't "Stream".
然而Iterable不能“流”。
Any better idea how to use streams (without converting Iterable to List)?
如何使用流(不转换为Iterable列表)有更好的想法吗?
8 个解决方案
#1
453
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, its 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.) Its also less code:
有一个比直接使用spliteratorUnknownSize更好的答案,既简单又能得到更好的结果。Iterable有一个spliterator()方法,所以您应该使用它来获取spliterator。在最坏的情况下,它的代码是相同的(默认实现使用spliteratorUnknownSize),但在更常见的情况下,迭代已经是一个集合,您将获得更好的spliterator,从而获得更好的流性能(甚至是更好的并行性)。它也更少的代码:
StreamSupport.stream(iterable.spliterator(), false)
.filter(...)
.moreStreamOps(...);
As you can see, getting a stream from an Iterable (see Why does Iterable<T> not provide stream() and parallelStream() methods?) is not very painful.
正如您所看到的,从Iterable获取流(参见为什么Iterable
#2
45
If you can use Guava library, since version 21, you can use
如果您可以使用Guava库,因为版本21可以使用。
Streams.stream(iterable)
#3
18
You can easily create a Stream
out of an Iterable
or Iterator
:
您可以很容易地从迭代器或迭代器中创建流:
public static <T> Stream<T> stream(Iterable<T> iterable) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
iterable.iterator(),
Spliterator.ORDERED
),
false
);
}
#4
8
I would like to suggest using JOOL library, it hides spliterator magic behind the Seq.seq(iterable) call and also provides a whole bunch of additional useful functionality.
我想建议使用JOOL库,它隐藏了Seq.seq(iterable)调用背后的spliterator魔法,并提供了大量其他有用的功能。
#5
2
I've created this class:
我创建了这个类:
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);
}
}
I think it's perfectly readable because you don't have to think about spliterators and booleans (isParallel).
我认为它是完全可读的,因为你不需要考虑spliterators和boolean (isParallel)。
#6
2
A very simple work-around for this issue is to create a Streamable<T>
interface extending Iterable<T>
that holds a default <T> stream()
method.
这个问题的一个非常简单的解决方法是创建一个可流式的
interface Streamable<T> extends Iterable<T> {
default Stream<T> stream() {
return StreamSupport.stream(spliterator(), false);
}
}
Now any of your Iterable<T>
s can be trivially made streamable just by declaring them implements Streamable<T>
instead of Iterable<T>
.
现在任何可迭代的
#7
2
So as another answer mentioned Guava has support for this by using:
另外一个回答提到番石榴有支持这一点的方法是:
Streams.stream(iterable);
I want to highlight that the implementation does something slightly different than other answers suggested. If the Iterable
is of type Collection
they cast it.
我想强调的是,该实现与建议的其他答案略有不同。如果Iterable是类型集合,则对它进行强制转换。
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
);
}
#8
0
If you happen to use Vavr(formerly known as Javaslang), this can be as easy as:
如果您碰巧使用Vavr(以前称为Javaslang),这可以简单到:
Iterable i = //...
Stream.ofAll(i);
#1
453
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, its 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.) Its also less code:
有一个比直接使用spliteratorUnknownSize更好的答案,既简单又能得到更好的结果。Iterable有一个spliterator()方法,所以您应该使用它来获取spliterator。在最坏的情况下,它的代码是相同的(默认实现使用spliteratorUnknownSize),但在更常见的情况下,迭代已经是一个集合,您将获得更好的spliterator,从而获得更好的流性能(甚至是更好的并行性)。它也更少的代码:
StreamSupport.stream(iterable.spliterator(), false)
.filter(...)
.moreStreamOps(...);
As you can see, getting a stream from an Iterable (see Why does Iterable<T> not provide stream() and parallelStream() methods?) is not very painful.
正如您所看到的,从Iterable获取流(参见为什么Iterable
#2
45
If you can use Guava library, since version 21, you can use
如果您可以使用Guava库,因为版本21可以使用。
Streams.stream(iterable)
#3
18
You can easily create a Stream
out of an Iterable
or Iterator
:
您可以很容易地从迭代器或迭代器中创建流:
public static <T> Stream<T> stream(Iterable<T> iterable) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
iterable.iterator(),
Spliterator.ORDERED
),
false
);
}
#4
8
I would like to suggest using JOOL library, it hides spliterator magic behind the Seq.seq(iterable) call and also provides a whole bunch of additional useful functionality.
我想建议使用JOOL库,它隐藏了Seq.seq(iterable)调用背后的spliterator魔法,并提供了大量其他有用的功能。
#5
2
I've created this class:
我创建了这个类:
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);
}
}
I think it's perfectly readable because you don't have to think about spliterators and booleans (isParallel).
我认为它是完全可读的,因为你不需要考虑spliterators和boolean (isParallel)。
#6
2
A very simple work-around for this issue is to create a Streamable<T>
interface extending Iterable<T>
that holds a default <T> stream()
method.
这个问题的一个非常简单的解决方法是创建一个可流式的
interface Streamable<T> extends Iterable<T> {
default Stream<T> stream() {
return StreamSupport.stream(spliterator(), false);
}
}
Now any of your Iterable<T>
s can be trivially made streamable just by declaring them implements Streamable<T>
instead of Iterable<T>
.
现在任何可迭代的
#7
2
So as another answer mentioned Guava has support for this by using:
另外一个回答提到番石榴有支持这一点的方法是:
Streams.stream(iterable);
I want to highlight that the implementation does something slightly different than other answers suggested. If the Iterable
is of type Collection
they cast it.
我想强调的是,该实现与建议的其他答案略有不同。如果Iterable是类型集合,则对它进行强制转换。
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
);
}
#8
0
If you happen to use Vavr(formerly known as Javaslang), this can be as easy as:
如果您碰巧使用Vavr(以前称为Javaslang),这可以简单到:
Iterable i = //...
Stream.ofAll(i);