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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/44261253/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 01:27:04  来源:igfitidea点击:

When I need to use Optional.orElseGet() over Optional.orElse()

javajava-8optional

提问by TVK

I need clear explanation on this, even though I read this linkon differences but no clear clarity. So anyone explain me on this in short with code.

我需要对此进行清楚的解释,即使我阅读了有关差异的链接但不清楚。所以任何人都可以用代码简短地解释我。

采纳答案by Ole V.V.

I think I am starting to understand your question. Execution order with Optionalcan be different from what we are used to in procedural programming (the same is true for Java streams and other code using lambdas).

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

I will use the two examples from Eugene's answer:

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

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

This is plain old Java: it's a call to orElse()taking new MyObject()as argument. So the argument is evaluated first and a new MyObjectcreated. This is then passed to orElse(). orElse()looks to see whether a value is present in the Optional; if so it returns that value (discarding the newly created object); if not, it returns the object given to it in the argument. This was the simpler example.

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

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

Again we have a method call with one argument, and again the argument is evaluated first. The lambda is only created and passed as a supplier. The code inside { }is not executed yet (you also see no Should I see thisin Eugene's output). Again orElseGetlooks to see if there is a value present in the Optional. If there is, the value is returned and the supplier we passed is ignored. If there isn't, the supplier is invoked, the code inside { }is executed to get the value to be returned from orElseGet().

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

In the first case, one may say that a MyObjectis created and wasted. In the second a Supplieris created and wasted. What you get in return is terse and null-pointer safe code in both cases. So very often it's not important which one you pick. If creating the MyObjectis costly or has unwanted side effects, you will of course want the second version where the object is only created when it is asked for, and is never wasted. Eugene in a comment mentions the case where the returned object comes from a database call. Database calls are usually time-consuming enough that you don't want to make one for no purpose.

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

回答by Eugene

How about an example:

举个例子:

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

And some usage:

还有一些用法:

  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();
    });

And some output:

还有一些输出:

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

In case Optionalhas a value; orElseis still called but not used. On the contradictory orElseGetis not called.

如果Optional有一个值orElse仍被调用但未使用。就矛盾orElseGet不叫。

Consider the case when creating the object is expensive; which one you will use?

考虑创建对象代价高昂的情况;你会使用哪一种?

It's actually easier to understand I think if you look in the code:

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

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

回答by nxhoaf

As answered here, you might want to consider the second approach when the required resource is expensive to get.

正如此处所回答的,当所需资源的获取成本很高时,您可能需要考虑第二种方法。

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

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