考虑以下具有用户偏好系统的应用程序用例:
我们想要获取偏好 MyFlag
的 bool 值。
在最好的情况下,我们希望它来自当前用户的设置。
如果失败,我们希望从默认设置中获取 MyFlag
。
如果失败,则抛出。
设置在服务器上。此连接很慢,可能会失败。
获取设置和获取首选项也可能全部失败。
所以让我们使用 javas Optionals:
public static boolean getMyFlag()throws NoSuchElementException
{
return getUserOrDefaultPreference("MY_FLAG");
}
private Boolean getUserOrDefaultPreference(String preferenceName) throws NoSuchElementException
{
return Optional.ofNullable(getConnection()) // get slow connection
.map(connection -> connection.getUserSettings()) // get user settings
.map(settings -> settings.getPref(preferenceName)) // return preference
.orElse(slowlyGetDefaultPreference(preferenceName)); // or else return default value
}
private Boolean slowlyGetDefaultPreference(String preferenceName) throws NoSuchElementException
{
return Optional.ofNullable(getConnection()) // get slow connection
.map(connection -> connection.getDefaultSettings()) // get default settings
.map(settings -> settings.getPref(preferenceName)) // return preference
.orElseThrow(() -> new NoSuchElementException()); // if any of the above fails throw
}
这里的问题是连接速度可能非常慢。当 .orElse(slowlyGet...);
被调用时,函数 slowlyGetDefaultPreference()
首先被评估,不管我的可选是空的还是有一个值。这是一种性能损失,我必须避免。
我尝试通过 .orElseGet(() -> slowlytGet..)
使用供应商,但这导致了同样的问题。
所以我唯一的办法是丑陋的 isPresent()
反模式,从可读性的角度来看,它破坏了整个可选流程:
private Boolean getUserOrDefaultPreference(String preferenceName) throws NoSuchElementException
{
Optional<Boolean> opt = Optional.ofNullable(getConnection())
.map(connection -> connection.getUserSettings())
.map(settings -> settings.getPref(preferenceName));
if(opt.isPresent())
{
return opt.get();
}
else
{
slowlyGetDefaultPreference(preferenceName));
}
}
抛出异常也是如此,因为我不想支付构建异常的成本。
我是不是遗漏了什么,或者这是唯一的解决方案吗?
最佳答案
orElse()
和 orElseGet(lambdas)
的区别是,第一个函数总是被调用,但是 orElseGet
被调用,当Optional.ofNullable()
中 orElseGet
之前的某些对象为 null。
这意味着,如果你不想每次都从orElse()
调用方法,你必须使用orElseGet()
在您的示例中,对于您的方法slowlyGetDefaultPreference(preferenceName)
,请使用orElseGet()
return Optional.ofNullable(getConnection()) // get slow connection
.map(connection -> connection.getUserSettings()) // get user settings
.map(settings -> settings.getPref(preferenceName)) // return preference
.orElseGet(() -> slowlyGetDefaultPreference(preferenceName));
那么当 map 函数中的所有对象都不是 null
关于java - Optional 的 `orElse` 惰性评估失败导致性能下降,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42108486/