Как реализовать оператор Elvis в Java 8?

У меня есть классический случай "Elvis operator", где я вызываю методы, которые каждый может возвращать null и связывать их вместе:

thing?:nullableMethod1(a)?:nullableMethod2(b)?:nullableMethod3()

В Java 8 наиболее верная реализация, которую я нашел, выглядит примерно так:

return Optional.ofNullable(thing)
    .flatMap(x -> Optional.ofNullable(x.nullableMethod1(a)))
    .flatMap(y -> Optional.ofNullable(y.nullableMethod2(b)))
    .flatMap(z -> Optional.ofNullable(z.nullableMethod3()))

Я хочу, чтобы Java Optional было что - то похожее на оператор Элвиса:

public<U> Optional<U> elvisOperator(Function<? super T, ? extends U> mapper) {
    return flatMap(t -> Optional.ofNullable(mapper.apply(t));
}

Чтобы мне не пришлось обернуть каждое возвращаемое значение:

return Optional.ofNullable(thing)
    .elvisOperator(x -> x.nullableMethod1(a))
    .elvisOperator(y -> y.nullableMethod2(b))
    .elvisOperator(Z::nullableMethod3); // also nice

Существует ли более эффективный и идиоматический способ реализации шаблона оператора Elvis в Java 8?

Ответ 1

Возможно, я что-то пропускаю, но есть ли причина, по которой вы не можете использовать Optional#map?

В следующем примере ничего не печатается, поскольку Optional является короткой замыкающей в том смысле, что если значение внутри Optional не существует (оно равно null или Optional пустое), оно считается пустым.

Optional.ofNullable("test")
        .map(s -> null)
        .ifPresent(System.out::println);

По этой причине, я думаю, вы могли бы просто сделать следующее:

return Optional.ofNullable(thing)
               .map(x -> x.nullableMethod1(a))
               .map(y -> y.nullableMethod2(b))
               .map(Z::nullableMethod3);

Это будет отображать вашу thing если она существует, или вернуть пустой Optional противном случае.