怎样将一个可选项映射为一个原始可选项?

4

我知道可以将一个Optional映射为另一个包装类型的可选项。

Optional<Long> millis(Date date) {
    return ofNullable(date).map(Date::getTime);
}

我该如何将mapflatMap应用到OptionalLong

OptionalLong millis(Date date) {
}

我尝试过,但没有成功。

ofNullable(value).flatMap(v -> { // javac has never liked me
    return OptionalLong.of(v.getTime());
});
4个回答

7

您可以使用 map 来获取一个 Optional<OptionalLong>,然后使用 orElse 移除外层的 Optional,示例如下:

OptionalLong millis(Date date) {
    return Optional.ofNullable(date).map(Date::getTime)
            .map(OptionalLong::of).orElse(OptionalLong.empty());
}

另外一种(在这种情况下更短的)方法是使用三元运算符:

OptionalLong millis(Date date) {
    return date == null ? OptionalLong.empty() : OptionalLong.of(date.getTime());
}

或者如果您已经有了 Optional<Long>

OptionalLong toOptionalLong(Optional<Long> o) {
    return o.map(OptionalLong::of).orElse(OptionalLong.empty());
}
OptionalLong toOptionalLong(Optional<Long> o) {
    return o.isPresent() ? OptionalLong.of(o.get()) : OptionalLong.empty();
}

3
请记住,如果您以任何方式涉及Optional<Long>,在此方案中会导致性能下降。来自Joshua Bloch的《Effective Java, 3rd Edition》:
“返回包含装箱基本类型的可选项与返回原始类型相比代价过高,因为可选项具有两个装箱级别而不是零级。 [...] 因此您永远不应该返回装箱基本类型的可选项,仅有可能例外是“次要基本类型”,即BooleanByteCharacterShortFloat。”
这里没有涉及使用Optional的原因。最好的解决方案是自己进行null检查,然后返回一个OptionalLong,例如:
OptionalLong millis(Date date) {
    return date == null ? OptionalLong.empty() : OptionalLong.of(date.getTime());
}

1
嗯,说“没有理由”这种话在我看来非常主观。一个简单的原因可能是可读性。对于Java,我们并不总是追求最有效的解决方案,只要两者具有相同的O运行时间(比如在这种情况下是O(1))。此外,OP提供的代码可能只是一个示例。如果您已经有了Optional<Long>,我们可能会选择“更好”的解决方案。 - Neuron
好的,可读性可能是一个合理的原因。我的主要反对意见是,你最终得到的代码看起来非常漂亮,但在幕后却不必要地从 long 转换为 Long,再转换为 Optional<Long>,然后再转换为 Long,再转换为 long,最终又转换为 OptionalLong - Joshua Bone

1
我会这样实现它:
OptionalLong toOptionalLong(Optional<Long> optionalValue) {
    return optionalValue.map(OptionalLong::of).orElseGet(OptionalLong::empty);
}

只有当optionalValue为空时,才会调用函数OptionalLong::empty

但是我不确定除非我真的被迫这样做,否则我会将Optional<Long>转换为OptionalLong。正如以前的答案所说,在这种情况下使用三元运算符可能是更好的方法。


1
使用 StreamEx 库
OptionalLong millis(final Date date) {  
   return StreamEx.ofNullable(date).mapToLong(Date::getTime).findAny();
}

or

OptionalLong toLong(Optional<Long> o) {
    return  StreamEx.of(o).mapToLong(Long::longValue).findAny();
}

or

OptionalLong toLong(final Optional<Date> o) {
    return StreamEx.of(o).mapToLong(Date::getTime).findAny();
}

1
免责声明:optional仅在代码片段中用作演示目的的参数。 - foal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接