How can I turn a Stream into an Iterable?
As explained in Why does Stream<T> not implement Iterable<T>?, an Iterable
bears the expectation to be able to provide an Iterator
more than once, which a Stream
can’t fulfill. So while you can create an Iterable
out of a Stream
for an ad-hoc use, you have to be careful about whether attempts to iterate it multiple times could exist.
Since you said, “I need to pass those parts of string as an Iterable
to a specific library”, there is no general solution as the code using the Iterable
is outside your control.
But if you are the one who creates the stream, it is possible to create a valid Iterable
which will simply repeat the stream construction every time an Iterator
is requested:
Iterable<String> lines = () -> "this\nthat\nthe_other".lines().iterator();
This fulfills the expectation of supporting an arbitrary number of iterations, while not consuming more resources than a single stream when being traversed only once.
for(var s: lines) System.out.println(s);
lines.forEach(System.out::println);
System.out.println(String.join("\n", lines));
tl;dr
Just cast, no need to convert.
Cast Stream < String >
to Iterable < String >
.
Details
CAUTION See Answer by Holger explaining dangers of using a stream-backed Iterable
.
Yes, you can make an Iterable
from a Stream
.
The solution is simple, but not obvious. See this post on Maurice Naftalin's Lambda FAQ.
The iterator()
method on BaseStream
(superclass of Stream
) returning a Iterator
happens to coincide with the same name of the iterator()
method returning an Iterator
as required by the Iterable
interface. The method signatures match. So we can actually cast the Stream
to a Iterable
, no conversion needed.
Make your input.
String input = "this\n" +
"that\n" +
"the_other";
Stream < String > stream = input.lines() ;
Cast that Stream<String>
to Iterable<String>
.
Iterable< String > iterable = ( Iterable < String > ) stream ; // Cast `Stream < String >` to `Iterable < String >`.
Test the results.
for ( String s : iterable :: iterator )
{
System.out.println( "s = " + s );
}
See this code run live at IdeOne.com.
s = this
s = that
s = the_other
CAVEAT Beware of the risk of stream-backed Iterable
. Explained in the correct Answer by Holger.