1. введение
API Необязательно обычно имеет два метода, которые могут вызвать путаницу: или Еще() и или еще Get() .
В этом кратком руководстве мы рассмотрим разницу между этими двумя и рассмотрим, когда использовать каждый из них.
2. Подписи
Давайте сначала начнем с основ, посмотрев на их подписи:
public T orElse(T other) public T orElseGet(Supplier extends T> other)
Очевидно, что or Else() принимает любой параметр типа T , тогда как orElseGet() принимает функциональный интерфейс типа Supplier , который возвращает объект типа T .
Теперь, основываясь на их Javadocs :
- or Else() : возвращает значение, если оно присутствует, в противном случае возвращает другое
- или же Get(): возвращает значение, если оно присутствует, в противном случае вызовите другое и верните результат его вызова
3. Различия
Легко немного запутаться в этих упрощенных определениях, поэтому давайте копнем немного глубже и рассмотрим некоторые реальные сценарии использования.
3.1. Орел()
Предполагая, что наш регистратор настроен правильно, давайте начнем с написания простого фрагмента кода:
String name = Optional.of("baeldung") .orElse(getRandomName());
Обратите внимание, что getRandomName () – это метод, который возвращает случайное имя из списка имен :
public String getRandomName() { LOG.info("getRandomName() method - start"); Random random = new Random(); int index = random.nextInt(5); LOG.info("getRandomName() method - end"); return names.get(index); }
При выполнении нашего кода мы найдем ниже сообщения, напечатанные в консоли:
getRandomName() method - start getRandomName() method - end
Переменная name будет содержать “baeldung” в конце выполнения кода.
С его помощью мы можем легко сделать вывод, что параметр из or Else() вычисляется даже при наличии непустого Необязательного .
3.2. орЕлсеГет()
Теперь давайте попробуем написать аналогичный код с помощью или Get() :
String name = Optional.of("baeldung") .orElseGet(() -> getRandomName());
Приведенный выше код не будет вызывать метод getRandomName () .
Помните (из Javadoc), что S поставщик метод, переданный в качестве аргумента, выполняется только тогда, когда необязательный значения нет.
Таким образом, использование orElseGet() для вашего случая сэкономит нам некоторое время, затрачиваемое на вычисление случайного имени .
4. Измерение Влияния На Производительность
Теперь, чтобы также понять различия в производительности, давайте использовать JMH и посмотрим некоторые фактические цифры:
@Benchmark @BenchmarkMode(Mode.AverageTime) public String orElseBenchmark() { return Optional.of("baeldung").orElse(getRandomName()); }
И или Еще Get() :
@Benchmark @BenchmarkMode(Mode.AverageTime) public String orElseGetBenchmark() { return Optional.of("baeldung").orElseGet(() -> getRandomName()); }
При выполнении наших эталонных методов мы получаем:
Benchmark Mode Cnt Score Error Units orElseBenchmark avgt 20 60934.425 ± 15115.599 ns/op orElseGetBenchmark avgt 20 3.798 ± 0.030 ns/op
Как мы видим, влияние на производительность может быть существенным даже для такого простого сценария использования.
Приведенные выше цифры могут немного отличаться, однако orElseGet() явно превзошел или еще() для нашего конкретного примера.
В конце концов, or Else() включает в себя вычисление метода getRandomName() для каждого запуска.
5. Что важно?
Помимо аспектов производительности, другие факторы, заслуживающие внимания, включают в себя:
- Что делать, если метод выполнит некоторую дополнительную логику? Например, сделает некоторые вставки или обновления БД
Даже когда мы назначаем объект параметру or Else() :
мы все еще создаем “Другой” объект без причины
И именно поэтому для нас важно принять тщательное решение между OrElse() и orElseGet() в зависимости от наших потребностей – по умолчанию имеет смысл использовать orElseGet() каждый раз, если объект по умолчанию уже не построен и доступен напрямую.
6. Заключение
В этой статье мы изучили нюансы между необязательными методами OrElse() и orElseGet () . Мы также заметили, что иногда такие простые понятия могут иметь более глубокий смысл.
Как всегда, полный исходный код можно найти на Github .