Я пытаюсь понять разницу между Optional<T>.orElse()
и Optional<T>.orElseGet()
методами.
Описание orElse()
метода: «Вернуть значение, если оно есть, в противном случае вернуть другое».
Описание orElseGet()
метода для этого метода: «Вернуть значение, если оно есть, в противном случае вызвать другое и вернуть результат этого вызова».
orElseGet()
Метод принимает функциональный интерфейс поставщика, который по существу не принимает никаких параметров и возвращает T
.
В какой ситуации вам нужно использовать orElseGet()
? Если у вас есть метод, T myDefault()
почему бы вам просто не сделать, optional.orElse(myDefault())
а optional.orElseGet(() -> myDefault())
?
Не похоже, что orElseGet()
это откладывает выполнение лямбда-выражения на какое-то более позднее время или что-то в этом роде, так какой в этом смысл? (Я бы подумал, что было бы более полезно, если бы он вернул более безопасный Optional<T>
, который get()
никогда не выбрасывает NoSuchElementException
и isPresent()
всегда возвращает true ... но, очевидно, это не так, он просто возвращает T
как orElse()
).
Есть ли какая-то другая разница, по которой я скучаю?
orElseGet
он вызывает поставщика, только если значение отсутствует.orElse()
сmyDefault()
методом еще называют, но ее возвращаемое значение просто не используется.orElseGet()
может привести к некоторым серьезным ошибкам: medium.com/alphadev-thoughts/...Ответы:
Возьмите эти два сценария:
Если
opt
не содержит значение, два действительно эквивалентны. Но еслиopt
действительно содержит значение, сколькоFoo
объектов будет создано?Ps: конечно, в этом примере разница, вероятно, не будет ощутимой, но если вам нужно получить значение по умолчанию, например, из удаленного веб-сервиса или из базы данных, оно вдруг становится очень важным.
источник
Foo
объект, в то время как в первом случае он будет создавать его, но не будет использовать его, если внутри значения есть значениеOptional
.System.out.println()
это не расчет, а утверждение, дающее заметный побочный эффект. И я уже говорил, что наблюдаемые побочные эффекты будут препятствовать оптимизации (поток вывода консоли является внешним ресурсом).Короткий ответ:
Optional.isPresent()
значенияOptional.isPresent() == false
В реальном коде вы можете рассмотреть второй подход, когда требуемый ресурс дорогостоящий .
Для более подробной информации рассмотрим следующий пример с этой функцией:
Разница как ниже:
Когда
optional.isPresent() == false
нет разницы между двумя способами. Однако, когдаoptional.isPresent() == true
,orElse()
всегда вызывает последующую функцию , хотите ли вы этого или нет.И наконец, используемый тестовый пример, как показано ниже:
Результат:
Код:
источник
Optional.isPresent() == false
вместо этого (ложь, не правда)Optional.orElse
государствIf a value is present, returns the value, otherwise returns other
может подразумевать такое поведение ...orElse()
работает аналогичноfinally
вtry-catch
выражении. Я прав?Я потянулся сюда за проблемой, о которой говорил Кудо .
Я делюсь своим опытом с другими.
orElse
илиorElseGet
вот в чем вопрос:печать
orElse
оценивает значение B () независимо от значения необязательного. Таким образом,orElseGet
ленив.источник
B()
к методу с именемorElse()
илиabc()
он не имеет никакого значения,B()
оценивается.or
префиксов дезориентирует разработчиков ( в том числе себя , когда я спросил проблему), думая , что это короткое замыкание операции, потому что это то , что мы привыкли в логических условиях. Однако это не так, это просто имя метода, имеющееor
префикс, поэтому его аргументы будут оцениваться независимо от того,Optional
содержит значение значение или нет. К сожалению, наименование сбивает с толку, но мы ничего не можем с этим поделать.Я бы сказал, что самая большая разница между
orElse
иorElseGet
возникает, когда мы хотим что-то оценить, чтобы получить новое значение вelse
условии.Рассмотрим этот простой пример -
Теперь давайте преобразуем приведенный выше пример в использование
Optional
вместе сorElse
:Теперь давайте преобразуем приведенный выше пример в использование
Optional
вместе сorElseGet
:Когда
orElse
вызывается,apicall().value
он оценивается и передается методу. Принимая во внимание, что в случаеorElseGet
оценки происходит только еслиoldValue
пусто.orElseGet
позволяет ленивые оценки.источник
Следующий пример должен продемонстрировать разницу:
Ответ также появляется в документах.
public T orElseGet(Supplier<? extends T> other)
:Supplier
Не будет вызываться , если наOptional
подарки. в то время как,public T orElse(T other)
:Если
other
это метод, который возвращает строку, она будет вызвана, но ее значение не будет возвращено, еслиOptional
существует.источник
Разница довольно тонкая, и если вы не будете обращать особого внимания, вы будете использовать ее неправильно.
Лучший способ понять разницу между
orElse()
иorElseGet()
заключается в том,orElse()
что всегда будет выполняться, если значениеOptional<T>
равно нулю или нет , ноorElseGet()
будет выполняться только когда значениеOptional<T>
равно нулю. .Словарь orElse означает следующее : - выполнить часть, когда чего-то нет, но здесь это противоречит, см. Пример ниже:
Контрольные показатели :
Надеюсь, это прояснит сомнения таких людей, как я, которые хотят получить самый простой пример из жизни :)
источник
Прежде всего, проверьте объявление обоих методов.
1) OrElse: выполнить логику и передать результат в качестве аргумента.
2) OrElseGet: выполнить логику, если значение внутри необязательного равно нулю
Некоторое объяснение вышеупомянутой декларации: Аргумент «Optional.orElse» всегда выполняется независимо от значения объекта в необязательном порядке (null, пусто или со значением). При использовании «Optional.orElse» всегда учитывайте вышеупомянутый момент, в противном случае использование «Optional.orElse» может быть очень рискованным в следующей ситуации.
Риск-1) Проблема с журналированием: если содержимое внутри orElse содержит какой-либо оператор журнала: в этом случае вы будете регистрировать его каждый раз.
Риск-2) Проблема с производительностью: Если содержимое внутри orElse требует много времени : Содержимое, требующее много времени, может представлять собой любые операции ввода-вывода, вызов БД, вызов API, чтение файла. Если мы поместим такой контент в orElse (), система в итоге выполнит бесполезный код.
Риск-3) Недопустимое состояние или ошибка: если содержимое внутри orElse изменяет некоторое состояние объекта: мы можем использовать этот же объект в другом месте, скажем, внутри функции Optional.map, и это может привести к критической ошибке.
Тогда, когда мы можем пойти с orElse ()? Предпочитайте использовать orElse, когда значением по умолчанию является некоторый константный объект enum. Во всех вышеупомянутых случаях мы можем использовать Optional.orElseGet () (который выполняется только тогда, когда Optional содержит непустое значение) вместо Optional.orElse (). Зачем?? В orElse мы передаем значение результата по умолчанию, но в orElseGet мы передаем Supplier, а метод Supplier выполняется только в том случае, если значение в Optional равно null.
Основные выводы из этого:
Я объяснил это в пункте 2 ( «Optional.map/Optional.orElse»! = «If / else» ) моего среднего блога. Используйте Java8 как программист, а не как кодер
источник
Учитывая следующий код:
если мы получаем
value
таким образом:Optional.<String>ofNullable(null)
нет никакой разницы между orElseGet () и OrElse (), но если мы получимvalue
таким образом:Optional.<String>ofNullable("test")
,orelesMethod()
вorElseGet()
не будет называться , но вorElse()
нем будет называтьсяисточник