过滤可选值的最小值

use*_*344 3 java optional java-8 java-stream

我想获取对象列表的函数结果的最小值。但是这个函数的返回值是可选的。所以如果到目前为止没有设置片段时间就可以了,然后返回值应该是Optional.empty()

public Optional<Double> getFragmentTime(int fragment) {
    ...
}

private List<Entry> entries; // will be filled in the ctor.

public Optional<Double> getMinFragmentTime(int fragment) {
    return entries.stream()
       .map(e -> e.getFragmentTime(fragment))
       .filter(Optional::isPresent)
       .map(Optional::get)
       .min(Double::compare);
}
Run Code Online (Sandbox Code Playgroud)

这是存档的正确方法吗?这两个函数调用.filter(Optional.isPresent).map(Optional.get)对我来说似乎很奇怪,我认为必须有更好的解决方案。

Nik*_*las 7

您可以使用Optional::stream以来可用的平面映射的优势:

return entries.stream()                         // Stream<Entry>
        .map(e -> e.getFragmentTime(fragment))  // Stream<Optional<Double>>
        .flatMap(Optional::stream)              // Stream<Double>
        .min(Double::compare);                  // Optional<Double>
Run Code Online (Sandbox Code Playgroud)

请注意,这.min(Double.compare);是不正确的用法,参数实际上是 lambda 表达式((d1, d2) -> Double.compare(d1, d2),应缩短为方法引用Double::compare。也可以使用Comparator.comparingDouble(d -> d)

情况下,你必须坚持使用.filter(Optional::isPresent).map(Optional::get).

  • 它是但是平面映射后生成的流仅包含一个值。平面映射使内部结构变得平坦。假设您有 Stream&lt;Stream&lt;E&gt;&gt; 并通过平面映射实现 Stream&lt;E&gt;。同样,它是可选的,始终最多保留一项。Optional::stream 返回一个空 Stream 或一个带有该元素的 Stream,以确保只有当前值保留在 Stream 中。如果您使用 map 而不是 flatmap,则会得到上述 Stream&lt;Stream&lt;E&gt;&gt; 的结果,并且随后调用自平坦映射会导致 Stream&lt;E&gt; 中的结果,就像我的解决方案一样。 (2认同)
  • 为什么不使用单个`.flatMap(e -&gt; e.getFragmentTime(fragment).stream())`。除此之外,我会使用 `min(Comparator.naturalOrder())` 而不是创建一个新的比较器。 (2认同)
  • 尝试尽可能多地使用方法引用似乎是一种普遍的习惯。典型的模式是“map(Type::collectionReturningMethod) .flatMap(Collection::stream)”。目前还不清楚哪个更有效,无论如何差异都很小。我倾向于假设,考虑到当前的实现,使用 lambda 的单个操作会获胜,但是,如上所述,优势很小。当其中一个操作中已经有 lambda 表达式时,很明显,与使用 lambda 表达式的单个操作相比,使用两个操作无论如何都不会获胜。 (2认同)
  • 这类问题需要认真写。例如,避免任何类似“什么更好”的内容,并强调“幕后发生的事情”或“它们在技术上有何不同”以及“它如何影响性能”方面。但请注意,有[一个旧的类似问答](/sf/ask/1683834141/),因此只有在解决新方面(例如更深入的技术细节)时,新问题才是合理的(并且该问题需要写成这样,这种差异是可识别的)。 (2认同)