How to create a Java 8 Stream from an iterator?

This doesn't create a stream, but Iterator also has a method called forEachRemaining:

someIterator.forEachRemaining(System.out::println);
someIterator.forEachRemaining(s -> s.doSomething());
//etc.

The argument you pass in is a Consumer which is the same thing you pass to Stream::forEach.

Here are the docs for that method. note that you can't continue the "chain" like you can with a stream. But I've still found this helpful the few times I've wanted a Stream from an Iterator.


For the particular example of NavigableSet.descendingIterator(), I think the simplest way is to use NavigableSet.descendingSet() instead.

But given you are probably interested in the more general case, the following seems to work:

import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.TreeSet;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

public class Streams {
    public static void main(String... args) {
        TreeSet<String> set = new TreeSet<>();
        set.add("C");
        set.add("A");
        set.add("B");

        Iterator<String> iterator = set.descendingIterator();

        int characteristics = Spliterator.DISTINCT | Spliterator.SORTED | Spliterator.ORDERED;
        Spliterator<String> spliterator = Spliterators.spliteratorUnknownSize(iterator, characteristics);

        boolean parallel = false;
        Stream<String> stream = StreamSupport.stream(spliterator, parallel);

        stream.forEach(System.out::println); // prints C, then B, then A
    }
}

In short, you have to create a Spliterator from the Iterator first using one of the static methods in Spliterators. Then you can create a Stream using the static methods in StreamSupport.

I don't have that much experience with creating Spliterators and Streams by hand yet, so I can't really comment on what the characteristics should be or what effect they will have. In this particular simple example, it didn't seem to matter whether I defined the characteristics as above, or whether I set it to 0 (i.e. no characteristics). There is also a method in Spliterators for creating a Spliterator with an initial size estimate - I suppose in this particular example you could use set.size(), but if you want to handle arbitrary Iterators I guess this won't be the case. Again, I'm not quite sure what effect it has on performance.


static <T> Stream<T> iteratorToFiniteStream(final Iterator<T> iterator) {
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
}

static <T> Stream<T> iteratorToInfiniteStream(final Iterator<T> iterator) {
    return Stream.generate(iterator::next);
}