java 合并选项的最佳方式是什么?

gkl3eglg  于 2023-03-11  发布在  Java
关注(0)|答案(9)|浏览(179)

以下是我目前的发现:

Optional<Foo> firstChoice = firstChoice();
Optional<Foo> secondChoice = secondChoice();
return Optional.ofNullable(firstChoice.orElse(secondChoice.orElse(null)));

这让我觉得既可怕又浪费。如果firstChoice存在,我就不必要地计算secondChoice。
还有一个更高效的版本:

Optional<Foo> firstChoice = firstChoice();
if(firstChoice.isPresent()) {
 return firstChoice;
} else {
 return secondChoice();
}

在这里,如果不复制Map器或声明另一个局部变量,我就不能将某个Map函数链接到末尾,所有这些都使得代码比实际要解决的问题更复杂。
我更愿意这样写:

return firstChoice().alternatively(secondChoice());

但是可选的::显然不存在。现在怎么办?

zy1mlcev

zy1mlcev1#

你可以简单地把它替换成

Optional<Foo> firstChoice = firstChoice();
return firstChoice.isPresent()? firstChoice : secondChoice();

除非 firstChoice.isPresent() 为false,否则上面的代码不会调用。
但是你必须准备好调用这两个函数来得到你想要的输出。没有其他的方法来逃避检查。

  • 最佳情况是First choice返回true。
  • 最坏的情况是First choice返回false,因此对Second choice调用另一个方法。
8xiog9wr

8xiog9wr2#

下面是@marstran解决方案对任意数量期权的推广:

@SafeVarargs
public static <T> Optional<T> selectOptional(Supplier<Optional<T>>... optionals) {
    return Arrays.stream(optionals)
            .reduce((s1, s2) -> () -> s1.get().map(Optional::of).orElseGet(s2))
            .orElse(Optional::empty).get();
}

试验:

public static Optional<String> first() {
    System.out.println("foo called");
    return Optional.empty();
}

public static Optional<String> second() {
    System.out.println("bar called");
    return Optional.of("bar");
}

public static Optional<String> third() {
    System.out.println("baz called");
    return Optional.of("baz");
}

public static void main(String[] args) {
    System.out.println(selectOptional(() -> first(), () -> second(), () -> third()));
}

输出:

foo called
bar called
Optional[bar]
dfty9e19

dfty9e193#

我对java 8不支持这一点感到非常沮丧,于是我切换回guava的可选函数,它有or

public abstract Optional<T> or(Optional<? extends T> secondChoice)

如果此可选项存在值,则返回它;否则为第二选择。

uttx8gqw

uttx8gqw4#

Java 9为这种情况添加了Optional.or​(Supplier<? extends Optional<? extends T>> supplier)方法。
给定方法firstChoice()secondChoice(),它们都返回Optional<Foo>,下面的一行程序使用Optional.or来获得所需的结果:

return firstChoice().or(this::secondChoice);

这种方法还有一个额外的好处,即只在firstChoice为空时计算secondChoice

dfuffjeb

dfuffjeb5#

惰性计算和任意数量的Optional元素

Stream.<Supplier<Optional<Foo>>>of(
        this::firstChoice,
        this::secondChoice
).map(
        Supplier::get
).filter(
        Optional::isPresent
).findFirst(
).orElseGet(
    Optional::empty
);
x8goxv8g

x8goxv8g6#

使用Java11,您可以简单地执行firstChoice().or(this::secondChoice)

bkkx9g8r

bkkx9g8r7#

以下是一种适用于流API中任意数量的Optional的方法:

return Arrays.asList(firstChoice, secondChoice).stream()
  .filter(Optional::isPresent)
  .map(Optional::get)
  .findFirst().orElse(null);

这不是最短的一个,但更明白易懂。
另一种方法是使用commons-lang的Guava中的firstNonNull(),如果你已经在使用其中一个库的话:

firstNonNull(firstChoice.orElse(null), secondChoice.orElse(null));
6yoyoihd

6yoyoihd8#

试试这个:

firstChoice().map(Optional::of)
             .orElseGet(this::secondChoice);

map方法给你一个Optional<Optional<Foo>>,然后orElseGet方法把它扁平化回Optional<Foo>secondChoice方法只有在firstChoice()返回空的可选值时才会被计算。

rt4zxlrg

rt4zxlrg9#

也许是这样的:

Optional<String> finalChoice = Optional.ofNullable(firstChoice()
    .orElseGet(() -> secondChoice()
    .orElseGet(() -> null)));

出发地:Chaining Optionals in Java 8

相关问题