Я хочу прекратить выполнение потока, когда будет найдено первое значение. Однако, когда я запускаю код ниже, он показывает, что вызываются два метода, даже если значение присутствует из метода первый.
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();
}
Я проверил в документах, что:
Return {@code true} if there is a value present, otherwise {@code false}.
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
Как прекратить выполнение, если присутствует первое значение, и не выполнять метод второй?




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
Хороший вопрос, я тоже не большой поклонник актерского состава. буду менять :)
Вместо .findFirst() .flatMap(Function.identity()) вы также можете использовать .findFirst() .orElse(Optional.empty()) или .map(Optional::get) .findFirst(). Кажется, это повторяющийся вопрос, но найти его с помощью функции поиска Stackoverflow действительно очень сложно…
Проблема не в том, что findFirst не закорачивает, а в том, что Stream.of(first(), second()) вызывает немедленное (а не отложенное) выполнение first() и second. По сути, оно оценивается как любое обычное выражение.
Другими словами, даже если ваш основной метод просто
final public static void main(String[] args) throws Exception {
Stream.of(first(), second());
}
Он по-прежнему будет немедленно выполнять first() и second().
Stream<Supplier<Optional<String>>> supplierStream = Stream.of(Test::first, Test::second); Optional<String> s = supplierStream...может улучшить читаемость.