javajava-streamspliterator

Converting an iterator to a list results in an empty list


I have the equivalent of, from here:

Iterator<String> sourceIterator = Arrays.asList("A", "B", "C").iterator();
sourceIterator.forEachRemaining(source -> System.out.println(source)); // prints out all elements
Iterable<String> iterable = () -> sourceIterator;
List<String> targetList = StreamSupport.stream(iterable.spliterator(), false).
    .collect(Collectors.toList());
System.out.println(targetList.isEmpty()) // prints true

I've added in some debugging print statements to help me, before I figured out the way to do the conversion. But it turns out that the stream is empty. So I'm wondering if my contents or my method is not quite right?

Reading up on forEachRemaining it says:

Performs the given action for each remaining element until all elements have been processed or the action throws an exception. Actions are performed in the order of iteration, if that order is specified. Exceptions thrown by the action are relayed to the caller.

It doesn't looks like it removes anything from the iterator, so I don't think it's that.


Solution

  • Playing with the code, it looks like forEachRemaining does empty the stream. Without that line, the stream does not end up empty. The linked explanation of iterator in the question gives this default implementation:

    while (hasNext())
        action.accept(next());
    

    Which will empty the iterator. This is not the same as the spliterator which:

    invokes tryAdvance(java.util.function.Consumer<? super T>)

    Not next(), but regardless, you cannot iterate twice.