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

TVK*_*TVK 12 java optional java-8

我需要对此进行清楚的解释,即使我读到这个关于差异的链接但没有明确的清晰度.所以任何人都可以用代码向我解释这一点.

Ole*_*.V. 36

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

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

    o1.orElse(new MyObject()); // 1055e4af 
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • 喜欢!你的措辞是完美的IMO.一加 (2认同)

Eug*_*ene 13

一个例子怎么样:

static class MyObject {
    public MyObject() {
        System.out.println("Creating one..." + this);
    }
}
Run Code Online (Sandbox Code Playgroud)

一些用法:

  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();
    });
Run Code Online (Sandbox Code Playgroud)

还有一些输出:

 Creating one... MyObject@7382f612
 Creating one... MyObject@1055e4af
Run Code Online (Sandbox Code Playgroud)

如果Optional 有价值 ; orElse仍被调用但未使用.关于矛盾orElseGet并没有被称为.

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

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

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