Stream
inherits an iterator() method to produce an Iterator
.
But I need an Iterable
rather than an Iterator
.
For example, given this string:
String input = "this\n" +
"that\n" +
"the_other";
…I need to pass those parts of string as an Iterable
to a specific library. Calling input.lines()
yields a Stream
. So I would be set if I could make that Stream
into a Iterable
of its elements.
CopyTo(Stream) Reads the bytes from the current stream and writes them to another stream. Both streams positions are advanced by the number of bytes copied.
From the documentation: A stream should be operated on (invoking an intermediate or terminal stream operation) only once. A stream implementation may throw IllegalStateException if it detects that the stream is being reused. So the answer is no, streams are not meant to be reused.
In Java 8, we can use Stream. iterate to create stream values on demand, so called infinite stream.
Given an Iterable, the task is to convert it into Stream in Java. Examples: Approach: Get the Iterable. Convert the Iterable to Spliterator using Iterable.spliterator() method. Convert the formed Spliterator into Sequential Stream using StreamSupport.stream() method. Return the stream.
Iterator to Stream – Java 8 Iterator to stream follows the same path as Iterable to stream. The only difference is that the Iterator interface has no spliterator () method so we need to use Spliterators.spliteratorUnknownSize () method to get the spliterator.
The only difference is that the Iterator interface has no spliterator () method so we need to use Spliterators.spliteratorUnknownSize () method to get the spliterator. Rest everything is same. 3. Iterator to Stream – Java 9
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));
Just cast, no need to convert.
Cast Stream<String>::iterator
to Iterable<String>
.
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 signature of the iterator
method of BaseStream
(superclass of Stream
) returning a Iterator
matches the only method of the functional interface Iterable
, so the method reference Stream<T>::iterator
can be used as an instance of Iterable<T>
. (The fact that both methods have the same name is coincidental.)
Make your input.
String input = "this\n" +
"that\n" +
"the_other";
Stream<String> stream = input.lines() ;
Use the method reference to generate a Iterable<String>
.
Iterable< String > iterable = stream::iterator;
Test the results.
for ( String s : iterable )
{
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With