Say you want to stream the elements of an iterator; let's use a concrete example of a Scanner
, which implements Iterator<String>
.
Given an Iterator
, say:
// Scanner implements Iterator<String>
Iterator<String> scanner = new Scanner(System.in);
Options to create a Stream<String>
from it are the clunky:
StreamSupport.stream(
Spliterators.spliteratorUnknownSize(scanner, Spliterator.ORDERED), false);
or the slightly more terse, but obtuse:
StreamSupport.stream(
((Iterable<String>) () -> new Scanner(System.in)).spliterator(), false);
Is there a factory method somewhere in the JDK that returns a Stream<T>
given an Iterator<T>
?
I would simply use Stream.generate(iterator::next)
. Yes, it is an infinite stream, but so is the scanner from System.in
, unless you know how many lines you're asking for in which case it's easy enough to use
Stream.generate(iterator::next).limit(numLines);
This prevents the iterator from having to be iterated twice (once as the iterator, once as the stream).
If you need a sized stream without knowing how big it will be, but don't want to clutter your code just create a utility method that explicitly takes an Iterable<T>
:
public static <T> Stream<T> stream(Iterable<T> it){
return StreamSupport.stream(it.spliterator(), false);
}
It ends up being more legible than trying to cram it all on one line, and
then you can just call stream(()->iterator);
or stream(()->new Scanner(System.in));
You can add the second convenience method easily enough, too:
public static <T> Stream<T> stream(Iterator<T> it){
return stream(()->it);
}
enabling you to call stream(iterator);
or stream(new Scanner(System.in));
Although, if I were going to read System.in
into a stream, I'd probably use a Reader rather than a Scanner anyway:
return new BufferedReader(new InputStreamReader(System.in)).lines();