我很好奇为什么Java的Optional没有提供类似于
但我认为这只是对
自Java 9以来,可以将
此外,也可以使用
我是否误用了
Stream
的peek
方法。
Stream
接口的peek
方法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<User>
(参见 CrudRepository#findById))
但由于 Optional
上没有 peek
方法,所以它无法编译。
因此,如果没有 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;
};
}
}
并使用 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
方法。)
还是说这被认为不值得呢?
ifPresent()
已经足够了。 - JB NizetUser user = repository.findById().orElseThrow(...); logger.debug("...", user, id); return user
。只需三行代码,如果存在该值,则会将其记录下来。如果这是使用情况,那么设计者认为它是多余的也就不足为奇了。 - RealSkepticrepository.findById(id).stream().peek(...).findAny().orElseThrow(...)
,但这仍然是一种达到您想要的方式的hackish方法。 这个问题绝对值得点赞,并且我也希望有一个适当的答案。 - Ilario