I think I've run into an issue with an assumption I made: if a spliterator's item isn't consumed by a stream, the spliterator will still be able to advance to it. It seems like this is not the case.
Here's some code to demonstrate:
import java.util.Spliterator;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* Created by dsmith on 7/21/15.
*/
public class SpliteratorTest {
public static void main(String[] args) {
System.out.println("Test 1");
test1();
System.out.println("Test 2");
test2();
}
public static void test1() {
final Spliterator<String> spliterator1 = Stream.of("a", "b", "c", "d", "e", "f").spliterator();
StreamSupport.stream(spliterator1, false).
limit(3).
collect(Collectors.toList());
System.out.println("spliterator1.estimateSize() = " + spliterator1.estimateSize());
}
public static void test2() {
final Spliterator<String> spliterator1 = Stream.of("a", "b", "c", "d", "e", "f").spliterator();
final Spliterator<String> spliterator2 = Stream.of("1", "2", "3", "4", "5", "6").spliterator();
Stream.of(StreamSupport.stream(spliterator1, false), StreamSupport.stream(spliterator2, false)).
flatMap(Function.identity()).
limit(3).
collect(Collectors.toList());
System.out.println("spliterator1.estimateSize() = " + spliterator1.estimateSize());
System.out.println("spliterator2.estimateSize() = " + spliterator2.estimateSize());
}
}
This outputs:
Test 1
spliterator1.estimateSize() = 3
Test 2
spliterator1.estimateSize() = 0
spliterator2.estimateSize() = 6
I understand that spliterators can be split... but it seems like non-split, sequential access would intuitively preserve non-consumed items.
In the test2, it seems spliterator1 is fully consumed after the stream. But in test1, it is not fully consumed.
Is there anything I can do to get the desired behavior, or am I just doing something I shouldn't be doing?
This is an implementation detail, but the way flatMap
currently works is that it doesn't split into its content or iterate over it one element at a time. It gobbles it all up in one go. If you do Stream.concat(...)
instead of flatMap
, you should see the difference:
Stream.concat(StreamSupport.stream(spliterator1, false), StreamSupport.stream(spliterator2, false)).
limit(3).
collect(Collectors.toList());
System.out.println("spliterator1.estimateSize() = " + spliterator1.estimateSize());
System.out.println("spliterator2.estimateSize() = " + spliterator2.estimateSize());
output:
spliterator1.estimateSize() = 3
spliterator2.estimateSize() = 6
am I just doing something I shouldn't be doing?
In short, yes. Streams library makes no promises in what state it will leave a spliterator after a partial traversal.
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