【问题标题】:Java 8 OptionalJava 8 可选
【发布时间】:2016-05-19 15:38:21
【问题描述】:

我想检查一个特定的对象大小是否大于 0。如果它大于 0,那么我想创建一个可选对象,如果不是,那么我想返回一个 Optional 空。这是java代码的长版:

if(fooA.size>0) {
    return Optional.of(new Foo());
} else {
    return Optional.empty();
}

有没有办法使用 java 8 的可选库将其压缩成一行?

【问题讨论】:

  • 您实际上是否有 Stream 的对象,您想以这种方式包装,还是只需要包装一个对象?如果你只想包装一个对象......为什么要使用Stream
  • 为什么您认为 Stream API 会在这里为您提供帮助?这是一个不错、简单且易读的代码。如果我们谈论的是集合,我可能会颠倒条件并使用fooA.isEmpty()fooA 的类型是什么?
  • return fooA.size > 0 ? Optional.of(...) : Optional.empty()?
  • fooA 的类是什么?

标签: java java-8 optional


【解决方案1】:

有没有办法使用 java 8 的可选库将其压缩成一行?

如果你坚持使用 Optional 类,你可以使用Optional.ofNullable(),如果条件不满足则直接传递null

return Optional.ofNullable(fooA.size > 0 ? new Foo() : null);

但请注意(如 Holger correctly states),与仅用三元语句替换 if/else 语句(如tobias_k 和 Holger 都在 their comments):

return fooA.size > 0 ? Optional.of(new Foo()) : Optional.empty();

1 第一行略短,我通常认为这是一个优势,但在这种情况下绝对微不足道,因为长度差异可以忽略不计。

【讨论】:

  • 但是让Optional 实现执行额外的null 检查没有任何优势。与return fooA.size > 0 ? Optional.of(new Foo()) : Optional.empty();相比,不保存四个源代码字符@
  • @Holger 当然,与自己执行检查相比没有任何优势,但它也不应该受到伤害,并且问题特别要求它。我想在我的答案中添加一条像你这样的行,但是当我提交它时,已经有人用所说的语句评论了这个问题。但可以肯定的是,我可以提一下。
【解决方案2】:

命令式方式

如果您决定坚持使用命令式编程,那么像您这样的 if-else 结构就可以了。它的可读性、可理解性和通过简单地减少代码行你什么也得不到(除非你为此获得报酬并想玩弄系统)。

(condition)?(true-branch):(false-branch) 结构很好,但如果过于复杂,可能会变得难以阅读。无论如何,一些自动格式化规则将它的每个部分放在单独的行中。所以使用前请三思。

将创建放在一行中的最简单方法是将实例化重构为单独的方法并调用它:

return newOptionalFoo(fooA.size > 0);

...

private Optional<Foo> newOptionalFoo(boolean condition) {
  if(condition) {
    return Optional.of(new Foo());
  } else {
    return Optional.empty();
  }
}

如果您想将其压缩为单行 - 命令式样式 - 请执行以下操作:

return condition ? Optional.of(new Foo()) : Optional.empty();    

功能方式

如果你想使用函数式编程,你不应该在可以避免的情况下混合使用函数式和命令式编程。 一种适当的功能方式是将fooA 包装到一个Optional 中,过滤条件并映射到Foo。所以如果条件不满足,它会映射到空的Optional。我更喜欢这种方式。

return Optional.of(fooA).filter(f -> f.size > 0).map(f -> new Foo());

或者,您可以创建FooOptional 并使用过滤器,以便如果过滤条件不匹配,则可选项变为空:

return Optional.of(new Foo()).filter(f -> fooA.size > 0);

但这将创建一个Foo 的实例,无论条件是真还是假。如果您想要延迟实例化,因为创建 Foo 很昂贵,您可以使用 Supplier 并在过滤后映射到 Foo

return Optional.of((Supplier<Foo>) Foo::new)
               .filter(s -> fooA.size > 0)
               .map(Supplier::get)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-27
    • 1970-01-01
    • 2017-05-01
    • 2020-11-28
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    相关资源
    最近更新 更多