jbx*_*jbx 183 java optional java-8
我试图理解Optional<T>.orElse()和Optional<T>.orElseGet()方法之间的区别.
该orElse()方法的描述是"如果存在则返回值,否则返回其他值".
虽然,该orElseGet()方法的描述是"如果存在则返回值,否则调用other并返回该调用的结果".
该orElseGet()方法采用供应商功能接口,基本上不接受任何参数和返回T.
你需要在哪种情况下使用orElseGet()?如果你有一个方法,你T myDefault()为什么不这样做optional.orElse(myDefault())而不是optional.orElseGet(() -> myDefault())?
似乎没有orElseGet()将lambda表达式的执行推迟到以后的某个时间或什么的,所以有什么意义呢?(我本以为如果它返回一个更安全Optional<T>的东西会更有用,它get()永远不会抛出一个NoSuchElementException并且isPresent()总是返回真实......但显然它不是,它只是返回T就像orElse()).
我还缺少其他一些差异吗?
biz*_*lop 154
采取以下两种情况:
Optional<Foo> opt = ...
Foo x = opt.orElse( new Foo() );
Foo y = opt.orElseGet( Foo::new );
Run Code Online (Sandbox Code Playgroud)
如果opt不包含值,则两者确实等价.但如果opt 确实包含一个值,那么Foo将创建多少个对象?
Ps:当然在这个例子中差异可能是不可测量的,但是如果你必须从远程Web服务或数据库中获取默认值,它突然变得非常重要.
nxh*_*oaf 89
简答:
Optional.isPresent()值是多少,orElse()总是会调用给定的函数,无论你是否需要它Optional.isPresent() == false在实际代码中,当需要的资源很昂贵时,您可能需要考虑第二种方法.
// Always get heavy resource
getResource(resourceId).orElse(getHeavyResource());
// Get heavy resource when required.
getResource(resourceId).orElseGet(() -> getHeavyResource())
Run Code Online (Sandbox Code Playgroud)
有关更多详细信息,请考虑以下使用此函数的示例:
public Optional<String> findMyPhone(int phoneId)
Run Code Online (Sandbox Code Playgroud)
区别如下:
X : buyNewExpensivePhone() called
+——————————————————————————————————————————————————————————————————+——————————————+
| Optional.isPresent() | true | false |
+——————————————————————————————————————————————————————————————————+——————————————+
| findMyPhone(int phoneId).orElse(buyNewExpensivePhone()) | X | X |
+——————————————————————————————————————————————————————————————————+——————————————+
| findMyPhone(int phoneId).orElseGet(() -> buyNewExpensivePhone()) | | X |
+——————————————————————————————————————————————————————————————————+——————————————+
Run Code Online (Sandbox Code Playgroud)
什么时候optional.isPresent() == false,两种方式没有区别.但是,当您无论是否需要时optional.isPresent() == true,orElse()始终调用后续函数.
最后,使用的测试用例如下:
结果:
------------- Scenario 1 - orElse() --------------------
1.1. Optional.isPresent() == true
Going to a very far store to buy a new expensive phone
Used phone: MyCheapPhone
1.2. Optional.isPresent() == false
Going to a very far store to buy a new expensive phone
Used phone: NewExpensivePhone
------------- Scenario 2 - orElseGet() --------------------
2.1. Optional.isPresent() == true
Used phone: MyCheapPhone
2.2. Optional.isPresent() == false
Going to a very far store to buy a new expensive phone
Used phone: NewExpensivePhone
Run Code Online (Sandbox Code Playgroud)
码:
public class TestOptional {
public Optional<String> findMyPhone(int phoneId) {
return phoneId == 10
? Optional.of("MyCheapPhone")
: Optional.empty();
}
public String buyNewExpensivePhone() {
System.out.println("\tGoing to a very far store to buy a new expensive phone");
return "NewExpensivePhone";
}
public static void main(String[] args) {
TestOptional test = new TestOptional();
String phone;
System.out.println("------------- Scenario 1 - orElse() --------------------");
System.out.println(" 1.1. Optional.isPresent() == true");
phone = test.findMyPhone(10).orElse(test.buyNewExpensivePhone());
System.out.println("\tUsed phone: " + phone + "\n");
System.out.println(" 1.2. Optional.isPresent() == false");
phone = test.findMyPhone(-1).orElse(test.buyNewExpensivePhone());
System.out.println("\tUsed phone: " + phone + "\n");
System.out.println("------------- Scenario 2 - orElseGet() --------------------");
System.out.println(" 2.1. Optional.isPresent() == true");
// Can be written as test::buyNewExpensivePhone
phone = test.findMyPhone(10).orElseGet(() -> test.buyNewExpensivePhone());
System.out.println("\tUsed phone: " + phone + "\n");
System.out.println(" 2.2. Optional.isPresent() == false");
phone = test.findMyPhone(-1).orElseGet(() -> test.buyNewExpensivePhone());
System.out.println("\tUsed phone: " + phone + "\n");
}
}
Run Code Online (Sandbox Code Playgroud)
Jin*_*won 60
我到达这里是为了Kudo提到的问题.
我正在为别人分享我的经验.
orElse或者orElseGet,这就是问题:static String B() {
System.out.println("B()...");
return "B";
}
public static void main(final String... args) {
System.out.println(Optional.of("A").orElse(B()));
System.out.println(Optional.of("A").orElseGet(() -> B()));
}
Run Code Online (Sandbox Code Playgroud)
版画
B()...
A
A
Run Code Online (Sandbox Code Playgroud)
dev*_*ang 35
我想说,当我们想要评估某些东西以获得条件中的新值时,orElse和之间的最大区别.orElseGetelse
考虑这个简单的例子 -
// oldValue is String type field that can be NULL
String value;
if (oldValue != null) {
value = oldValue;
} else {
value = apicall().value;
}
Run Code Online (Sandbox Code Playgroud)
现在,让我们改变上面的例子中,使用Optional随orElse,
// oldValue is Optional type field
String value = oldValue.orElse(apicall().value);
Run Code Online (Sandbox Code Playgroud)
现在,让我们改变上面的例子中,使用Optional随orElseGet,
// oldValue is Optional type field
String value = oldValue.orElseGet(() -> apicall().value);
Run Code Online (Sandbox Code Playgroud)
当orElse被调用时,apicall().value被评估并传递给该方法.然而,在orElseGet评估的情况下,只有在oldValue空的情况下才会发生.orElseGet允许懒惰评估.
首先检查这两个方法的声明。
\n1) OrElse:执行逻辑并将结果作为参数传递。
\npublic T orElse(T other) { \n return value != null ? value : other;\n}\nRun Code Online (Sandbox Code Playgroud)\n2) OrElseGet:如果可选值内的值为空则执行逻辑
\npublic T orElseGet(Supplier<? extends T> other) {\n return value != null ? value : other.get(); \n}\nRun Code Online (Sandbox Code Playgroud)\n对上述声明的一些解释: \n\xe2\x80\x9cOptional.orElse\xe2\x80\x9d 的参数始终被执行,无论可选对象的值如何(null、空或有值)。使用 \xe2\x80\x9cOptional.orElse\xe2\x80\x9d 时请务必考虑上述几点,否则在以下情况下使用 \xe2\x80\x9cOptional.orElse\xe2\x80\x9d 可能会非常危险情况。
\n风险-1) 日志记录问题:如果 orElse 中的内容包含任何日志语句:\n在这种情况下,您每次都会记录它。
\nOptional.of(getModel())\n .map(x -> {\n //some logic\n })\n .orElse(getDefaultAndLogError());\n \ngetDefaultAndLogError() {\n log.error("No Data found, Returning default");\n return defaultValue;\n}\nRun Code Online (Sandbox Code Playgroud)\n风险-2) 性能问题:如果 orElse 中的内容是时间密集型的:\n时间密集型内容可以是任何 I/O 操作 DB 调用、API 调用、文件读取。如果我们将这样的内容放入 orElse() 中,系统最终将执行无用的代码。
\nOptional.of(getModel())\n .map(x -> //some logic)\n .orElse(getDefaultFromDb());\n\ngetDefaultFromDb() {\n return dataBaseServe.getDefaultValue(); //api call, db call.\n}\nRun Code Online (Sandbox Code Playgroud)\n风险 3) 非法状态或错误问题:如果 orElse 中的内容正在改变某些对象状态:\n我们可能在另一个地方使用同一个对象,比如在Optional.map 函数中,它可能会让我们陷入严重错误。
\nList<Model> list = new ArrayList<>();\nOptional.of(getModel())\n .map(x -> {\n })\n .orElse(get(list));\n\nget(List < String > list) {\n log.error("No Data found, Returning default");\n list.add(defaultValue);\n return defaultValue;\n}\nRun Code Online (Sandbox Code Playgroud)\n那么,我们什么时候可以使用 orElse() 呢?\n当默认值是某个常量对象(枚举)时,首选使用 orElse。在上述所有情况下,我们可以使用Optional.orElseGet()(仅当Optional包含空值时执行)而不是Optional.orElse()。为什么??在orElse中,我们传递默认结果值,但在orElseGet中,我们传递Supplier,并且Supplier的方法仅在Optional中的值为null时执行。
\n从中得出的主要结论是:
\n我已经在 point-2 ( \xe2\x80\x9cOptional.map/Optional.orElse\xe2\x80\x9d != \xe2\x80\x9cif/else\xe2\x80\x9d ) 我的中等博客中解释了这一点。作为程序员而不是编码员使用 Java8
\n差异非常微妙,如果您不加注意,就会以错误的方式使用它。
\n\norElse()理解和之间区别的最佳方法orElseGet()是,无论是否为null都orElse()将始终执行,但仅在为null时才会执行。Optional<T>orElseGet()Optional<T>
orElse的字典含义是:-当某些东西不存在时执行该部分,但这里它矛盾,请参见下面的示例:
\n\n Optional<String> nonEmptyOptional = Optional.of("Vishwa Ratna");\n String value = nonEmptyOptional.orElse(iAmStillExecuted());\n\n public static String iAmStillExecuted(){\n System.out.println("nonEmptyOptional is not NULL,still I am being executed");\n return "I got executed";\n }\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n输出: nonEmptyOptional 不为 NULL,但我仍然被执行
\n
Optional<String> emptyOptional = Optional.ofNullable(null);\n String value = emptyOptional.orElse(iAmStillExecuted());\n public static String iAmStillExecuted(){\n System.out.println("emptyOptional is NULL, I am being executed, it is normal as \n per dictionary");\n return "I got executed";\n }\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n输出:emptyOptional为NULL,我正在被执行,根据\n字典这是正常的
\n\n对于
\norElseGet(),该方法按照字典的含义, 只有当Optional为\n nullorElseGet()时才会执行\n部分 。
基准:
\n\n+--------------------+------+-----+------------+-------------+-------+\n| Benchmark | Mode | Cnt | Score | Error | Units |\n+--------------------+------+-----+------------+-------------+-------+\n| orElseBenchmark | avgt | 20 | 60934.425 | \xc2\xb1 15115.599 | ns/op |\n+--------------------+------+-----+------------+-------------+-------+\n| orElseGetBenchmark | avgt | 20 | 3.798 | \xc2\xb1 0.030 | ns/op |\n+--------------------+------+-----+------------+-------------+-------+\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n备注: 对于我们的特定示例来说,
\norElseGet()其表现明显优于。orElse()
希望它能消除像我这样想要最基本的示例的人的疑虑:)
\n