Imagine having some sort of incoming data either by callback or an InputStream that you need to continuously convert into a Java 8 Stream. We don't know when the incoming data-stream stops, but we know that it can stop.
So far I've seen two ways of getting around this problem and I'm interested in the best practices on how to achieve this. Mainly because I this must be something someone has faced before. There must be a simpler way of doing it than the ideas below.
1) The most simple way is to treat the source as a Supplier and just use Stream.generate to serve data:
Stream.generate(() -> blockCallToGetData());
However, this has the disadvantage, that the stream never ends. So whenever an input source stops sending, the stream just keeps calling the method. Unless we throw a Runtime exception naturally, but this can get ugly fast.
2) The second idea is to use a Iterator (converted to a Spliterator) where the next method blocks until we find the next element. As a crude example:
class BlockingIterator implements Iterator<Data> {
@Override void boolean hasNext() {
return true;
}
@Override Data next() {
return blockCallToGetData();
}
}
The advantage of this is that I can stop the stream by returning false in the hasNext method. However, in situations where we do not control the speed of the incoming data (such as in a callback), we would need to keep a buffer of ready elements for the iterator. This buffer could grow infinitely big, before someone calls next on the iterator.
So, my question goes; what is the best practice for serving blocking input into a stream?