在Java流(或并行流)中返回之前,Optional.empty的“ Unwrap”可选

x80*_*486 2 java functional-programming java-stream

我在这个简单的事情上遇到了麻烦。我有一个返回的方法Optional<TypeA>

public Optional<TypeA> getFirst() {
  return set.stream().filter(it -> it.getStatus() == SUCCESS).findFirst(); // set is a Set<TypeA>
}
Run Code Online (Sandbox Code Playgroud)

...然后我从以下位置调用它:

public boolean hasFirst() {
  return types.parallelStream() // types is a List<TypeB> that has a Set<TypeA>
    .filter(it -> it.getTotalAmount() > 0)
    .map(TypeA::getFirst)
    .findFirst() // this can return an Optional[Optional.empty]
    .isPresent();
}
Run Code Online (Sandbox Code Playgroud)

问题是,Optional空的Optionaltrue按预期返回,所以我不知道如何正确处理此问题!

有什么线索吗?

Jor*_*nee 6

您可以使用Optional#flatMap“解包”内部可选内容:

public boolean hasFirst() {
   return types.parallelStream()
       .filter(it -> it.getTotalAmount() > 0)
       .map(TypeA::getFirst)
       .findFirst() // return Optional[Optional.empty]
       .flatMap(i -> i) // <---
       .isPresent(); // true
}
Run Code Online (Sandbox Code Playgroud)

如果存在一个值,则对它应用提供的带有可选参数的映射函数,返回该结果,否则返回一个空的Optional。


Hol*_*ger 5

使用.findFirst().isPresent()是一种常见的反模式。如果您只想知道是否有匹配项,则无需询问第一个匹配项,特别是如果您打算使用并行流,则搜索第一个匹配项而不是任何匹配项可能会带来显着的性能缺陷。所以findAny会更可取,但当您只想知道是否存在匹配时,根本没有必要询问值:

\n\n
public boolean hasFirst() {\n  return types.parallelStream() // types is a List<TypeB> that has a Set<TypeA>\n    .filter(it -> it.getTotalAmount() > 0)\n    .anyMatch(obj -> obj.getFirst().isPresent());\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

它\xe2\x80\x99s不清楚,你的原始代码应该如何工作,如果types是实例列表TypeB并且getFirst()是在 中声明的方法TypeA,如TypeA::getFirst所示,但是,我认为,你得到了图片 \xe2\x80\xa6

\n\n

我建议将该方法也重命名hasFirst()hasAny(). 当然,具有任何匹配元素的集合也会有一个元素,但是这种集中于 \xe2\x80\x9cfirst\xe2\x80\x9d 的做法会产生误导,特别是当元素TypeA位于 a 中时Set,这通常意味着不存在完全定义的顺序。

\n