当前位置: 首页 > 知识库问答 >
问题:

为什么Optional不提供peek方法?

寿飞飙
2023-03-14

我很想知道为什么Java的可选不提供类似于流的方法。

Stream接口的peekmethod javadoc声明:

  • @apiNote此方法主要用于支持调试,您希望在元素流经管道中的某个点时看到这些元素

这几乎完全描述了我的用例:

@Override
@Transactional
public User getUserById(long id) {
    return repository.findById(id)
        .peek(u -> logger.debug("Found user = {} by id = {}", u, id))
        .orElseThrow(() -> new UserNotFoundException("id = " + id));
}

repository.findById返回可选

但是它不会编译,因为 Optional 上没有 peek 方法

因此,如果没有< code>peek方法,上述所有内容都会转换为:

@Override
@Transactional
public User getUserById(long id) {
  Optional<User> userOptional = repository.findById(id);
  if (userOptional.isPresent()) {
    logger.debug("Found user = {} with id = {}", userOptional.get(), id);
  }
  return userOptional.orElseThrow(() -> new UserNotFoundException("id = " + id));
}

也可以这样做(参见此答案):

@NoArgsConstructor(access = PRIVATE)
public abstract class OptionalUtils {
    public static <T> UnaryOperator<T> peek(Consumer<T> consumer) {
        return t -> {
            consumer.accept(t);
            return t;
        };
    }
}

并将其与映射方法一起使用:

return repository.findById(id)
    .map(OptionalUtils.peek(u -> logger.debug("Found user = {} with id = {}", u, id)))
    .orElseThrow(() -> new UserNotFoundException("id = " + id));

但我认为这是一个黑客,而不是对可选的干净用法。

从Java 9开始,可以将< code>Optional转换为< code>Stream,但是该流没有< code > orelsthrow 方法(显然它不应该有)。

也可以使用<code>ifPresent。(对我来说,<code>如果存在</code>不应返回除<code>void</code>以外的任何内容。)

我是否误用了< code>Optional?

缺少peek方法是故意的吗?(但同时Vavr的Option确实提供了peek方法。)

还是只是被认为不值得?

共有3个答案

陶智
2023-03-14

已经有可选::ifPresent可选::isPresent方法来记录结果。但是您可能想要一些符合要求的东西。对此的答案可能是疏忽。

空翼
2023-03-14

嗯,只有设计师可以回答你“确切”的细节,说明为什么选项没有peek方法。

因此,现在,您只能使用<code>isPresent()

if (userOptional.isPresent()) 
    logger.debug("Found user = {} with id = {}", userOptional.get(), id);

或者,如果您希望将链接页面上的建议答案作为管道的一部分,您也可以考虑。

顺便说一句,考虑到JDK9中新的<code>流

return repository.findById(id) // Optional<User>
                 .stream()  // Stream<User>
                 .peek(u -> logger.debug("Found user = {} by id = {}", u, id)) // Stream<User>
                 .findFirst() // Optional<User>
                 .orElseThrow(() -> new UserNotFoundException("id = " + id))

类似的例子见这个回答。

刘英彦
2023-03-14

已经有接受消费者的可选::ifPresent方法。

在Java 8中,唯一的方法是使用< code>Optional::map,将实体映射到自身,并将其用作< code>peek方法:

return repository.findById(id)
                 .map(u -> {
                     logger.debug("Found user = {} with id = {}", u, id)
                     return u;
                 })
                 .orElseThrow(() -> new UserNotFoundException("id = " + id));

...这应该简化实现自己的窥视方法

<T> UnaryOperator<T> peek(Consumer<T> consumer) {
    return t -> {
        consumer.accept(t);
        return t;
    };
}

…并与<code>可选<code>一起舒适使用:

return repository.findById(id)
                 .map(this.peek(logger.debug("Found user = {} with id = {}", u, id)))
                 .orElseThrow(() -> new UserNotFoundException("id = " + id));
 类似资料:
  • 问题内容: 有人知道为什么JUnit 4提供但不提供方法吗? 它提供了(对应于)和(对应于),因此它们似乎没有包含在内就显得很奇怪。 顺便说一下,我知道JUnit插件提供了我正在寻找的方法。我只是出于好奇而问。 问题答案: 我建议您使用较新的样式断言,该断言可以轻松描述各种否定形式,并在断言失败时自动构建对您的期望和得到的结果的描述: 这三个选项都是等效的,请选择最容易阅读的一个。 要使用方法的简

  • 本质上,它包装了,确保了最大容量,并提供了一些其他有用的特性。更好的方法是直接将其实现为。 现在,为了方便起见,我认为最好实现,这样,如果您想要循环它,就可以使用增强的for-loops。(我的类还提供了方法,因此我认为是合理的。) 接口提供以下功能(省略了javadoc): null

  • groovy.lang.missingMethodException:方法的无签名:java.util.stream.referencePipeline$head.peek()适用于参数类型:(MolportFileverization$_run_closure1)值:[MolportFileverization$_run_closure1@d62472f]可能的解决方案:peek(java.ut

  • 问题内容: 我想知道为什么接口不提供和方法。考虑以下类别: 它是 一手 牌的一种实现,因为您在玩交易纸牌游戏时可以手拿牌。 本质上,它包装了,可确保最大容量并提供其他一些有用的功能。最好将其直接实现为。 现在,为了方便起见,我认为实现起来会很不错,这样,如果您想对其进行循环,则可以使用增强的for循环。(我的课程也提供了一种方法,因此我认为该方法是合理的。) 该界面提供了以下内容(省略了javad

  • 问题内容: 在Swift中处理可选选项的习惯用法似乎过于冗长,如果您只想在nil为零的情况下提供默认值,则它是: 涉及不必要地复制代码,或 这不需要是常数。 Scala的Option monad(与Swift的Optional基本相同)具有用于此目的的方法: 我想念什么吗?Swift已经有一种紧凑的方式做到这一点吗?否则,是否可以在扩展名中为Optional 定义? 问题答案: 更新资料 苹果现在

  • 问题内容: 查看Guava的ImmutableList(和其他一些类),您会发现很多重载的便捷方法(“按顺序返回包含给定元素的不可变列表”。)这些方法使用不同数量的参数: 一直到这一步: 我的一些同事认为这很愚蠢,想知道为什么不只有一种方法:。他们怀疑这是不正确的性能“优化”,属于“您认为自己比编译器更聪明”之类的东西。 我的直觉是Kevin Bourrillion等。出于真正的原因将这些方法放在