考虑具有用户偏好系统的应用程序的以下用例:
我们想要获得偏好的布尔值MyFlag。
在最好的情况下,我们希望它来自当前用户的设置。
如果失败,我们希望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
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是连接可能很慢。当.orElse(slowlyGet...);被调用时,slowlyGetDefaultPreference()首先评估func ,无论我的 optional 是空的还是有值。这是性能损失,我必须避免。
我尝试通过 使用供应商.orElseGet(() -> slowlytGet..),但这导致了同样的问题。
所以我唯一的办法是丑陋的isPresent()反模式,从可读性的角度来看,它破坏了整个 Optional 流程:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
抛出异常也是如此,因为我不想支付构建异常的成本。
我在这里遗漏了什么还是这是唯一的解决方案?
之间的区别orElse()和orElseGet(lambdas)是第一个函数总是被调用,但orElseGet被调用,当之前的一些obejctorElseGet在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));
Run Code Online (Sandbox Code Playgroud)
然后你编码不评估最后一个方法,当 map 函数中的所有对象都不是 null
当我测试它时,它只打印"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()));
}
}
Run Code Online (Sandbox Code Playgroud)