如何使用Java 8 Optionals,如果所有三个都存在,则执行操作?

2022-08-31 14:15:45

我有一些使用Java Optionals的(简化的)代码:

Optional<User> maybeTarget = userRepository.findById(id1);
Optional<String> maybeSourceName = userRepository.findById(id2).map(User::getName);
Optional<String> maybeEventName = eventRepository.findById(id3).map(Event::getName);

maybeTarget.ifPresent(target -> {
    maybeSourceName.ifPresent(sourceName -> {
        maybeEventName.ifPresent(eventName -> {
            sendInvite(target.getEmail(), String.format("Hi %s, $s has invited you to $s", target.getName(), sourceName, meetingName));
        }
    }
}

毋庸置疑,这看起来和感觉都很糟糕。但是我想不出另一种方法可以以一种不那么嵌套和更具可读性的方式做到这一点。我考虑过流式传输3个可选,但放弃了这个想法,因为做一个然后感觉更糟。.filter(Optional::isPresent).map(Optional::get)

那么,有没有一种更好、更“Java 8”或“自选识字”的方式来处理这种情况(基本上,计算最终操作都需要多个可选)


答案 1

我认为流三S是一种过度杀戮,为什么不简单Optional

if (maybeTarget.isPresent() && maybeSourceName.isPresent() && maybeEventName.isPresent()) {
  ...
}

在我看来,与使用流 API 相比,这更清楚地说明了条件逻辑。


答案 2

使用帮助器函数,事情至少会变得不嵌套:

@FunctionalInterface
interface TriConsumer<T, U, S> {
    void accept(T t, U u, S s);
}

public static <T, U, S> void allOf(Optional<T> o1, Optional<U> o2, Optional<S> o3,
       TriConsumer<T, U, S> consumer) {
    o1.ifPresent(t -> o2.ifPresent(u -> o3.ifPresent(s -> consumer.accept(t, u, s))));
}

allOf(maybeTarget, maybeSourceName, maybeEventName,
    (target, sourceName, eventName) -> {
        /// ...
});

明显的缺点是,对于每个不同的数量,您需要一个单独的帮助程序函数重载Optional


推荐