Ответ
Оба метода предоставляют значение по умолчанию для пустого Optional, но различаются моментом вычисления этого значения, что напрямую влияет на производительность.
orElse(T other)
- Вычисляет значение
otherнемедленно, в момент вызова метода, независимо от того, пустOptionalили нет. - Подходит для простых, дешевых констант или предварительно вычисленных значений.
Optional<String> foundName = findUserInCache(userId);
// Дорогой вызов БД произойдет ВСЕГДА, даже если пользователь найден в кэше
String name = foundName.orElse(fetchUserFromDatabase(userId)); // Неоптимально!
orElseGet(Supplier supplier)
- Вычисляет значение лениво, только если
Optionalдействительно пуст. - Принимает
Supplier— функциональный интерфейс, код которого выполняется по требованию. - Предпочтительный выбор для ресурсоемких операций (запросы к БД, сетевые вызовы, сложные вычисления).
Optional<String> foundName = findUserInCache(userId);
// Вызов fetchUserFromDatabase произойдет ТОЛЬКО если кэш пуст
String name = foundName.orElseGet(() -> fetchUserFromDatabase(userId)); // Оптимально
Ключевое отличие на примере
public String getDefaultValue() {
System.out.println("Вычисляю значение по умолчанию...");
return "Default";
}
Optional<String> fullOpt = Optional.of("Actual Value");
Optional<String> emptyOpt = Optional.empty();
// С orElse()
String result1 = fullOpt.orElse(getDefaultValue()); // Выведет: "Вычисляю значение по умолчанию..."
// result1 = "Actual Value", но побочный эффект выполнен!
String result2 = emptyOpt.orElse(getDefaultValue()); // Выведет: "Вычисляю значение по умолчанию..."
// result2 = "Default"
// С orElseGet()
String result3 = fullOpt.orElseGet(() -> getDefaultValue()); // Ничего не выведет!
// result3 = "Actual Value", вычисления не было
String result4 = emptyOpt.orElseGet(() -> getDefaultValue()); // Выведет: "Вычисляю значение по умолчанию..."
// result4 = "Default"
Вывод: Используйте orElseGet() для отложенных вычислений, особенно когда получение значения по умолчанию — дорогая операция.