当我需要在Optional.orElse()上使用Optional.orElseGet()时

时间:2017-05-30 11:39:11

标签: java java-8 optional

我需要对此作出明确的解释,即使我在差异上阅读link但没有明确的清晰度。因此,任何人都可以通过代码向我解释这一点。

3 个答案:

答案 0 :(得分:30)

我想我开始明白你的问题。 Optional的执行顺序可能与我们在程序编程中使用的顺序不同(Java流和使用lambdas的其他代码也是如此)。

我将使用Eugene’s answer中的两个示例:

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

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

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

我们再次使用一个参数进行方法调用,并再次首先计算参数。 lambda仅作为供应商创建和传递。 { }中的代码尚未执行(您在Eugene的输出中也看不到Should I see this)。再次orElseGet查看Optional中是否存在值。如果有,则返回该值,并忽略我们传递的供应商。如果没有,则调用供应商,执行{ }内的代码以获取从orElseGet()返回的值。

在第一种情况下,可以说创建了MyObject并浪费了。在第二个中,创建了Supplier并浪费了。你得到的回报是两种情况下的简洁和空指针安全代码。所以你选择哪一个并不重要。如果创建MyObject代价高昂或者有不必要的副作用,那么您当然需要第二个版本,其中仅在需要时才创建对象,并且永远不会浪费。评论中的Eugene提到了返回的对象来自数据库调用的情况。数据库调用通常非常耗时,您不希望出于任何目的。

答案 1 :(得分:12)

示例如何:

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

如果Optional 有值; orElse仍然被调用但未被使用。关于矛盾的orElseGet没有被称为。

考虑创建对象昂贵的情况;你将使用哪一个?

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

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

答案 2 :(得分:1)

回答here,当所需资源的获取成本昂贵时,您可能要考虑第二种方法。

// Always get heavy resource
getResource(resourceId).orElse(getHeavyResource()); 

// Get heavy resource when required.
getResource(resourceId).orElseGet(() -> getHeavyResource())