当我需要使用 Optional.orElseGet() over Optional.orElse()

2022-09-03 08:29:53

我需要对此有一个明确的解释,即使我阅读了这个关于差异的链接,但没有明确的清晰度。那么任何人都可以用代码向我简要解释一下吗?


答案 1

我想我开始理解你的问题了。执行顺序可能与我们在过程编程中习惯的顺序不同(对于使用lambda的Java流和其他代码也是如此)。Optional

我将使用尤金答案中的两个例子:

    o1.orElse(new MyObject()); // 1055e4af 

这是普通的旧Java:它是对作为论据的调用。因此,首先评估该参数并创建一个新参数。然后将其传递给 。 查看 ; 中是否存在值如果是这样,它将返回该值(丢弃新创建的对象);如果不是,它将返回参数中提供给它的对象。这是更简单的例子。orElse()new MyObject()MyObjectorElse()orElse()Optional

    o1.orElseGet(() -> {
        System.out.println("Should I see this");
        return new MyObject();
    });

同样,我们有一个带有一个参数的方法调用,并且首先评估该参数。lambda 仅作为供应商创建和传递。里面的代码还没有执行(你在Eugene的输出中也看不到)。再次查看 中是否存在值。如果有,则返回该值,并忽略我们传递的供应商。如果没有,则调用供应商,执行其中的代码以获取要从 返回的值。{ }Should I see thisorElseGetOptional{ }orElseGet()

在第一种情况下,可以说a是被创造和浪费的。在第二个中,a被创建并浪费。在这两种情况下,您得到的回报都是简洁和空指针安全代码。所以很多时候,你选择哪一个并不重要。如果创建成本高昂或具有不必要的副作用,您当然需要第二个版本,其中对象仅在被要求时才创建,并且永远不会浪费。Eugene在评论中提到了返回的对象来自数据库调用的情况。数据库调用通常非常耗时,您不想无缘无故地进行数据库调用。MyObjectSupplierMyObject


答案 2

举个例子怎么样:

static class MyObject {
    public MyObject() {
        System.out.println("Creating one..." + this);
    }
}

还有一些用法:

  Optional<MyObject> o1 = Optional.of(new MyObject()); // 7382f612

    o1.orElse(new MyObject()); // 1055e4af 
    o1.orElseGet(() -> {
        System.out.println("Should I see this");
        return new MyObject();
    });

和一些输出:

 Creating one... MyObject@7382f612
 Creating one... MyObject@1055e4af

如果具有值; 仍称为但未使用。关于矛盾不叫。OptionalorElseorElseGet

考虑创建对象成本高昂的情况;您将使用哪一个?

实际上,如果您查看代码,则更容易理解:

public T orElseGet(Supplier<? extends T> supplier) {
    return value != null ? value : supplier.get();
}

推荐