我很想知道为什么 Java 的 Optional不提供 peek
方法类似于 Stream
's one .
peek
方法 javadoc的 Stream
接口(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 开始,可以转换 Optional
至 Stream
但流中没有 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/