【问题标题】:How can I map an optional into a primitive optional?如何将一个可选项映射到一个原始可选项?
【发布时间】:2015-01-31 07:16:34
【问题描述】:

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

【问题讨论】:

    标签: java lambda optional


    【解决方案1】:

    您可以使用map 获取Optional&lt;OptionalLong&gt;,然后使用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&lt;Long&gt;

    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();
    }
    

    【讨论】:

      【解决方案2】:

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

      “与返回原始类型相比,返回一个包含装箱原始类型的可选项成本高得令人望而却步,因为可选项有两个级别的装箱而不是零。[...]因此你永远不应该返回一个可选项盒装的原始类型,“次要原始类型”可能除外,BooleanByteCharacterShortFloat"

      这里没有理由涉及Optional。最好的解决办法是自己做空检查,然后返回一个OptionalLong,例如

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

      【讨论】:

      • 好吧,说“没有理由”是非常主观的。一个简单的原因可能是可读性。对于 java,我们并不总是力求最有效的解决方案,只要两者具有相同的 O-runtime(如本例中的 O(1))。 OP提供的代码也可能只是一个例子。如果您已经有Optional&lt;Long&gt;,我们可能希望使用“更好”的解决方案
      • 好的,可读性可能是一个正当的理由。我的主要反对意见是你最终得到的代码看起来非常漂亮,但在幕后不必要地从 longLongOptional&lt;Long&gt;LonglongOptionalLong
      【解决方案3】:

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

      【讨论】:

      • 免责声明:可选在代码sn-ps中用作参数仅用于演示目的。
      【解决方案4】:

      我会按如下方式实现:

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

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

      但我不确定我是否会将Optional&lt;Long&gt; 转换为OptionalLong,除非我真的有义务这样做。正如之前的答案所说,在这种情况下,使用三元运算符可能是一种更好的方法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多