如何将可选映射到原始可选?

How can I map an optional into a primitive optional?

我知道我可以将 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());
});

您可以使用 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();
}

使用 StreamEx library

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

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

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

我会按如下方式实现它:

OptionalLong toOptionalLong(Optional<Long> optionalValue) {
    return optionalValue.map(OptionalLong::of).orElseGet(OptionalLong::empty);
}

函数 OptionalLong::empty 当且仅当 optionalValue 为空时被调用。

但我不确定我是否会将 Optional<Long> 转换为 OptionalLong 除非我真的不得不这么做。如之前的回答所述,在这种情况下使用三元运算符可能是更好的方法。

请记住,如果您以任何方式涉及 Optional<Long>,您 在这种情况下性能受到影响。来自 Joshua Bloch 的 Effective Java,第 3 版

"Returning an optional that contains a boxed primitive type is prohibitively expensive compared to returning the primitive type because the optional has two levels of boxing instead of zero. [...] Therefore you should never return an optional of a boxed primitive type, with the possible exception of the "次要原始类型,"BooleanByteCharacterShortFloat"

这里没有理由涉及Optional。最好的解决方案是自己进行空检查,然后 return 一个 OptionalLong,例如

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