考虑具有用户首选项系统的应用程序的以下用例:
我们希望得到偏好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...);
时,首先评估func 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));
}
}
同样适用于抛出异常,因为我不想支付构建异常的费用。
我在这里遗漏了什么或这是唯一的解决方案吗?
答案 0 :(得分:3)
当我测试它时,它只打印"smart"
:
public class SampleJava {
public static String stupid() {
System.out.println("stupid");
return "stupid";
}
public static void main(String[] args) {
System.out.println(Optional.ofNullable("smart").orElseGet(() -> stupid()));
}
}
答案 1 :(得分:3)
orElse()
和orElseGet(lambdas)
之间的区别在于,第一个函数始终被调用,但是orElseGet
被调用,而orElseGet
中Optional.ofNullable()
之前的一些对象被调用是空的。
这意味着,如果您不希望每次调用来自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