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