Поток до найденного значения - необязательно

Я хочу прекратить выполнение потока, когда будет найдено первое значение. Однако, когда я запускаю код ниже, он показывает, что вызываются два метода, даже если значение присутствует из метода первый.

public static void main(String[] args) {

        Optional<String> s = Stream.of(first(), second())
                .filter(Optional::isPresent)
                .findFirst()
                .flatMap(Function.identity());

        System.out.println(s.get());
    }

    private static Optional<String> first() {
        System.out.println("first");
        return Optional.of("someValue");
    }

    private static Optional<String> second() {
        System.out.println("second");
        return Optional.empty();
    }

Я проверил в документах, что:

  1. настоящее

Return {@code true} if there is a value present, otherwise {@code false}.

  1. найтиПервый()

Returns an {@link Optional} describing the first element of this stream, or an empty {@code Optional} if the stream is empty. If the stream has no encounter order, then any element may be returned.

Итак, первое условие выполнено, и второе, кажется, также выполнено, потому что оно возвращается:

first
second
someValue

Как прекратить выполнение, если присутствует первое значение, и не выполнять метод второй?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
0
93
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

How to quit execution if first value present, and not execute second method?

Stream#findFirst — терминальная операция короткого замыкания. Однако методы вызываются при вызове Stream.of(first(), second()). Это можно доказать с помощью следующего фрагмента:

Optional<String> s = Stream.of(first(), second())
                           .peek($ -> System.out.println("Hello World!"))
                           .filter(Optional::isPresent)
                           .findFirst()
                           .flatMap(Function.identity());

System.out.println(s.get());

Вывод:

first
second
Hello World!
someValue

Чтобы предотвратить выполнение first() и second() при вызове Stream#of, одним из решений было бы обернуть их в Supplier<Optional<String>>:

Stream<Supplier<Optional<String>>> stream = Stream.of(Test::first, Test::second);

Optional<String> s = stream.map(Supplier::get)
                           .filter(Optional::isPresent)
                           .findFirst()
                           .flatMap(Function.identity());

System.out.println(s.get());

Вывод:

first
someValue
Stream<Supplier<Optional<String>>> supplierStream = Stream.of(Test::first, Test::second); Optional<String> s = supplierStream... может улучшить читаемость.
Naman 12.02.2019 18:28

Хороший вопрос, я тоже не большой поклонник актерского состава. буду менять :)

Jacob G. 12.02.2019 18:46

Вместо .findFirst() .flatMap(Function.identity()) вы также можете использовать .findFirst() .orElse(Optional.empty()) или .map(Optional::get) .findFirst(). Кажется, это повторяющийся вопрос, но найти его с помощью функции поиска Stackoverflow действительно очень сложно…

Holger 13.02.2019 12:09

Проблема не в том, что findFirst не закорачивает, а в том, что Stream.of(first(), second()) вызывает немедленное (а не отложенное) выполнение first() и second. По сути, оно оценивается как любое обычное выражение.

Другими словами, даже если ваш основной метод просто

final public static void main(String[] args) throws Exception {
    Stream.of(first(), second());
}

Он по-прежнему будет немедленно выполнять first() и second().

Другие вопросы по теме