I have an interface which returns java.lang.Iterable<T>
.
I would like to manipulate that result using the Java 8 Stream API.
However Iterable can't "stream".
Any idea how to use the Iterable as a Stream without converting it to List?
I have an interface which returns java.lang.Iterable<T>
.
I would like to manipulate that result using the Java 8 Stream API.
However Iterable can't "stream".
Any idea how to use the Iterable as a Stream without converting it to List?
Iterable
has a spliterator()
method, which you can pass to StreamSupport.stream
to create a stream:
StreamSupport.stream(iterable.spliterator(), false)
.filter(...)
.moreStreamOps(...);
This is a much better answer than using spliteratorUnknownSize
directly, as it is both easier and gets a better result. In the worst case, it's 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). It's also less code.
As you can see, getting a stream from an Iterable
(see also this question) is not very painful.
Stream
would have been nice, e.g. Stream.ofIterable(iterable)
. –
Cangue If you can use Guava library, since version 21, you can use
Streams.stream(iterable)
Lists.newArrayList(Iterable)
. –
Wist 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
);
}
stream(...)
clutter your code? –
Calumny 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.
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.
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
);
}
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).
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>
.
If you happen to use Vavr(formerly known as Javaslang), this can be as easy as:
Iterable i = //...
Stream.ofAll(i);
© 2022 - 2024 — McMap. All rights reserved.
myIterable.stream()
does not exist! – ProcrusteanStream.of(iterable)
producesStream<Iterable<Object>>
. – Erl