java - 为什么 Optional 不提供 peek 方法?

标签 java lambda java-8 option-type java-9

我很想知道为什么 Java 的 Optional不提供 peek方法类似于 Stream 's one .

peek方法 javadocStream接口(interface)状态:

  • @apiNote This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline

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

@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<User> (参见 CrudRepository#findById ))

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

所以没有 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));
}

也可以这样做(参见 answer ):

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

并将其与 map 一起使用方法:

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

但我认为这是对 Optional 的 hack 而不是干净的使用.

从 Java 9 开始,可以转换 OptionalStream但流中没有 orElseThrow方法(显然不应该)。

也可以使用 ifPresent 来做同样的事情但它返回 void . (对我来说,ifPresent 似乎不应该返回除 void 以外的任何东西)

我在滥用 Optional 吗? ?

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

或者只是被认为不值得?

最佳答案

已经有 Optional::ifPresent接受 Consumer 的方法.

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

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

... 应简化实现自己的 peek 方法:

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

... 并与 Optional 一起舒适地使用:

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

关于java - 为什么 Optional 不提供 peek 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53580820/

相关文章:

java - 如何使用正则表达式模式检查字符串中每 12 个字符应该是 , ?

c++ - 具有单个参数的 bool 函数映射

java - 如何提交 Oracle Java 变更请求?

java - 如何让 spring-boot @Async 与 Java 8 一起工作

java - 类作为函数参数

java - 我们可以在 hibernate 条件查询中包含条件吗?

java - setText() 从数据库到 TextView

java - 使用 lambda 表达式计算偶数的平方

c# - 允许在 IEnumerable<MyObj> 上使用临时表达式

java - Lambda 表达式在一个接口(interface)上工作吗?