Есть ли класс в java 8, который реализует поток с нулевым завершением без необходимости сворачивать мои собственные?

Или есть лучший способ сделать это, что я пропал? Я хотел бы создать поток на основе поставщика (который обычно бесконечен), но поток прекращается, когда поставщик возвращает null. Я сделал это сам, но для выполнения довольно простой концепции кажется довольно много работы.

public class NullTerminatedStreamFactory {

    static int characteristics = Spliterator.ORDERED | Spliterator.DISTINCT;

    public static<T> Stream<T> makeNullTerminatedStream(Supplier<T> supplier) {
        return StreamSupport.stream(new NullTerminatedSpliteratorFromSupplier<>(supplier, Long.MAX_VALUE, characteristics), false);
    }

    static class NullTerminatedSpliteratorFromSupplier<T> extends Spliterators.AbstractSpliterator<T> {

        public NullTerminatedSpliteratorFromSupplier(Supplier<T> supplier, long est, int additionalCharacteristics) {
            super(est, additionalCharacteristics);
            this.supplier = supplier;
        }

        public Supplier<T> supplier;

        @Override
        public boolean tryAdvance(Consumer<? super T> action) {
            T next = supplier.get();
            if (next != null) {
                action.accept(next);
                return true;
            }
            return false;
        }
    }
}

Для записи я использую ее так, чтобы создать Stream из BlockingQueue:

NullTerminatedStreamFactory.makeNullTerminatedStream(() -> {
            try {
                BlockingQueue<Message> queue = getBlockingQueue();
                return queue.poll(1, TimeUnit.SECONDS);
            } catch (Exception e) {
                log.error("Exception while trying to get message from queue", e);
            }
            return null;
        });

Ответ 1

Вы уже нашли совершенно правильную реализацию вручную.

Как упоминалось в комментариях, Java 9, похоже, добавляет метод takeWhile(Predicate). До тех пор вы могли бы использовать стороннюю библиотеку, которая реализует нечто вроде takeWhile():

jOOλ

jOOλ имеет limitWhile(), что делает то же самое:

Seq.generate(supplier).limitWhile(Objects::nonNull);

(отказ от ответственности, я работаю в компании за jOOλ)

Javaslang

Javaslang реализовали свой собственный класс Stream, который вдохновлен коллекциями Scala и, следовательно, имеет takeWhile()

Stream.gen(supplier).takeWhile(Objects::nonNull);

Функциональная Java

Функциональная Java также поставляется со своей собственной реализацией Stream, которая имеет метод takeWhile():

Stream.fromFunction(i -> supplier.get()).takeWhile(o -> o != null);