Java 8 中的链式可选

新手上路,请多包涵

寻找一种链接可选值的方法,以便返回第一个存在的选项。如果不存在 Optional.empty() 应该被退回。

假设我有几种这样的方法:

 Optional<String> find1()

我正在尝试链接它们:

 Optional<String> result = find1().orElse( this::find2 ).orElse( this::find3 );

但当然这不起作用,因为 orElse 需要一个值,而 orElseGet 需要一个 Supplier

原文由 piler 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 629
2 个回答

使用流:

 Stream.of(find1(), find2(), find3())
    .filter(Optional::isPresent)
    .map(Optional::get)
    .findFirst();

如果您需要延迟评估查找方法,请使用供应商功能:

 Stream.of(this::find1, this::find2, this::find3)
    .map(Supplier::get)
    .filter(Optional::isPresent)
    .map(Optional::get)
    .findFirst();

原文由 Sauli Tähkäpää 发布,翻译遵循 CC BY-SA 3.0 许可协议

受 Sauli 的回答启发,可以使用 flatMap() 方法。

 Stream.of(this::find1, this::find2, this::find3)
  .map(Supplier::get)
  .flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
  .findFirst();

将 Optional 转换为 Stream 很麻烦。显然,这将 通过 JDK9 修复。所以这可以写成

Stream.of(this::find1, this::find2, this::find3)
  .map(Supplier::get)
  .flatMap(Optional::stream)
  .findFirst();

Java 9 发布后的更新

虽然原来的问题是关于Java 8的, Optional::or 是在Java 9中引入的。有了它,问题就可以解决如下

Optional<String> result = find1()
  .or(this::find2)
  .or(this::find3);

原文由 Indrek Ots 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题