是否有从Optional到Stream的便捷映射方法?

问题描述 投票:2回答:1

我有一个方法返回Optional<Foo>,如果它存在,我想使用该值来查找Stream<Bar>

现在我知道我可以这样做:

optionalFoo.map(foo->bars(foo)).orElse(Stream.empty());

(我使用完整形式的映射函数而不是方法参考来进行说明。)

使用Java 9+,我可以这样做:

optionalFoo.stream().flatMap(foo->bars(foo));

但无论哪种方式,额外的步骤似乎毫无意义。是否有一种映射方法可以简单地将可选项映射到流,或者如果不存在可选项,则将空流映射到空流中?然后我可以这样做:

optionalFoo.streamMap(foo->bars(foo));

如果没有这样的方法,为什么不呢?它可以作为一个简单的默认方法添加到Optional上。

最后,如果我必须编写自己的实用程序方法,上述哪种方法更有效(看到它们都提供相同的结果):映射到流或空流;或转换为流然后平面映射到流?我认为前者更有效,这说明了为什么需要一种实用方法。 (我们不想在整个地方重新输入.orElse(Stream.empty())。)

对于那些需要具体用例的人,假设有一种方法可以从DOM树返回HTML <head>元素:

/**
 * Finds the {@code <html><head>} element in the HTML namespace.
 * @param document The document tree.
 * @return A reference to the {@code <html><head>} element if it exists in the tree.
 */
public static Optional<Element> findHtmlHeadElement(@Nonnull final Document document);

现在另一种方法想要返回所有HTML <meta>元素(如果它们存在)。因此,它想要搜索<head>元素的子元素,但只有当它存在时才会被存在。 (请注意,childElementsByNameNS()是一个实用程序方法,它将另一个元素的子元素检索为Stream<Element>。)

/**
 * Finds the {@code <html><head><meta>} elements in an HTML document.
 * @param document The document tree.
 * @return A stream of {@code <html><head><meta>} elements if they exist in the tree.
 */
public static Stream<Element> htmlHeadMetaElements(@Nonnull final Document document) {
  return findHtmlHeadElement(document).map(headElement ->
      childElementsByNameNS(headElement, XHTML_NAMESPACE_URI_STRING, ELEMENT_META))
          .orElse(Stream.empty());
}

为什么我需要额外丑陋的.orElse(Stream.empty())样板?我宁愿有这样的事情:

/**
 * Finds the {@code <html><head><meta>} elements in an HTML document.
 * @param document The document tree.
 * @return A stream of {@code <html><head><meta>} elements if they exist in the tree.
 */
public static Stream<Element> htmlHeadMetaElements(@Nonnull final Document document) {
  return findHtmlHeadElement(document).streamMap(headElement ->
      childElementsByNameNS(headElement, XHTML_NAMESPACE_URI_STRING, ELEMENT_META));
}

你可能会说“你不能有从Optional到其他所有类型的特殊映射方法”,但是OptionalStream有一种特殊的关系。事实上,我有点认为Optional几乎是一个零或一个元素的Stream。事实上,这正是Optional.stream()回馈的内容。所以这是对Optional.stream()的补充。

java java-stream optional
1个回答
0
投票

关于这个问题:“为什么不'他们'将这种方法添加到可选中?”,首先是一个侧面故事。

'persona'是什么意思?

你会在字典中找到很多定义,绝对没有一个是词源上正确的定义,即“掩码”。你看,角色来自'per sonare':你说的话。一张面具。

可以说,“作者”这个词的人物角色认为它意味着“面具”。但是语言是动态的东西,它们的真正含义可能更多地取决于这个词的使用方式,而不是取决于作者的意思。

回到可选。

可选的作者(Brian Goetz和Oracle Lambda的其余部分)将其编写为流操作终端的解决方案,这对于空流可能没有意义。如果列表为空,list.stream().max(someComparator)的返回值是多少?而已。这就是j.u.Optional一直以来的意思。

社区中的一些人并没有那么用。有些人更喜欢scala的可选性:作为将无效信息传递到类型系统的“解决方案”。

这是非常不明智的建议。也许是无效的,因为动态概念存在问题,并且存在更好的解决方案(值得商榷,但超出了这个问题的范围,而不是重点),但是根据绝对没有研究或思考,对于可选的回答是可选的。显然很糟糕。我们已经可以看到这一点:Java已经成为地球上最流行的语言之一,已有20年历史,并且已经建立了一个巨大的图书馆生态系统,正如人们所期望的那样。你不能用向后兼容的方式替换返回X的返回Optional<X>的API,这意味着这些20年的库中的每一个最后一个都需要像昨天的垃圾一样被取出,因为没有办法转换API。

通常情况下,任何更新语言的提议都是可笑的,这些提议只需要几乎所有现有的库来发布更新。然而,如果整个社区采用可选择的返回值应以返回Optional<T>的形式通过API传达的概念,那么这正是需要的。

换句话说,“他们”(主要是Oracle,以及其他JCP)绝对不认为应该使用Optional。

然而,社区确实使用它。甲骨文仍然认为这意味着“面具”,一半的社区坚持认为它绝对意味着“面具”,但社区的另一半​​开始使用“人物角色”来表示戏剧中角色的概念。

怎么办?关于如何在java中修复'null',我有各种各样的想法,但首先你要讨论它是否是一个需要修复的问题。超出了这个问题的范围。

但是,希望这篇关于java的null以及Optional如何替代它的信息,可以说明为什么Oracle或JCP中的任何其他人“只是”将某些方法堆积到j.u.Optional中以使其更适合将其用作qazxswpoi。从API返回可选值的一般机制:因为他们认为(我会完全正确地定位),所以不应该使用该可选值。

© www.soinside.com 2019 - 2024. All rights reserved.