Following Stuart's idea, this could be done with a Spliterator
like this:
static <T> Stream<T> defaultIfEmpty(Stream<T> stream, Stream<T> defaultStream) {
final Spliterator<T> spliterator = stream.spliterator();
final AtomicReference<T> reference = new AtomicReference<>();
if (spliterator.tryAdvance(reference::set)) {
return Stream.concat(Stream.of(reference.get()), StreamSupport.stream(spliterator, stream.isParallel()));
} else {
return defaultStream;
}
}
I think this works with parallel Streams as the stream.spliterator()
operation will terminate the stream, and then rebuild it as required
In my use-case I needed a default Stream
rather than a default value. that's quite easy to change if this is not what you need