Java 8 Optional.orElse与orElseGet区别:《On Java 8》中文版性能陷阱
【免费下载链接】OnJava8 《On Java 8》中文版 项目地址: https://gitcode.com/gh_mirrors/on/OnJava8
你是否在使用Java 8的Optional类时,对orElse和orElseGet方法的选择感到困惑?这两个方法看似功能相似,实则存在显著差异,错误使用可能导致性能问题。本文将通过《On Java 8》中文版的知识点,结合实际场景,详细解析两者的区别及性能影响。
方法定义与基础区别
Optional类是Java 8引入的用于处理空指针异常的容器类。orElse和orElseGet是其常用的两个方法,用于在Optional对象为空时提供默认值。
orElse方法的定义为:
public T orElse(T other)
该方法接收一个T类型的参数,无论Optional对象是否为空,都会执行参数的创建过程。
orElseGet方法的定义为:
public T orElseGet(Supplier<? extends T> other)
该方法接收一个Supplier函数式接口,只有当Optional对象为空时,才会执行Supplier的get方法来获取默认值。
性能差异对比
无性能影响场景
当默认值是简单对象或基本类型时,两者的性能差异可以忽略不计。例如:
Optional<String> optional = Optional.ofNullable(null);
String value1 = optional.orElse("default");
String value2 = optional.orElseGet(() -> "default");
在这种情况下,两种方法的执行结果相同,性能差异微乎其微。
有性能影响场景
当默认值的创建成本较高时(如数据库查询、复杂对象创建等),两者的性能差异会变得明显。
以下是一个模拟高成本默认值创建的示例:
// 模拟高成本操作
public static String createExpensiveDefault() {
System.out.println("Creating expensive default value");
// 模拟耗时操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "expensive default";
}
public static void main(String[] args) {
Optional<String> optional = Optional.of("value");
// orElse无论optional是否为空都会执行createExpensiveDefault
String value1 = optional.orElse(createExpensiveDefault());
// orElseGet只有在optional为空时才会执行createExpensiveDefault
String value2 = optional.orElseGet(() -> createExpensiveDefault());
}
运行上述代码,控制台只会输出一次"Creating expensive default value",这是orElse方法执行的结果。而orElseGet方法由于optional不为空,没有执行createExpensiveDefault。
性能测试对比
为了更直观地展示两者的性能差异,我们进行一个简单的性能测试:
public static void main(String[] args) {
Optional<String> nonEmptyOptional = Optional.of("value");
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
nonEmptyOptional.orElse(createExpensiveDefault());
}
long orElseTime = System.currentTimeMillis() - startTime;
startTime = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
nonEmptyOptional.orElseGet(() -> createExpensiveDefault());
}
long orElseGetTime = System.currentTimeMillis() - startTime;
System.out.println("orElse耗时: " + orElseTime + "ms");
System.out.println("orElseGet耗时: " + orElseGetTime + "ms");
}
在这个测试中,orElse方法由于每次循环都会执行createExpensiveDefault,总耗时约为10000毫秒,而orElseGet方法几乎不耗时。
使用场景建议
使用orElse的场景
- 默认值是简单对象或基本类型
- 默认值的创建成本非常低
- 无论Optional是否为空,都需要执行默认值的创建逻辑
使用orElseGet的场景
- 默认值的创建成本较高
- 默认值的创建有副作用,不应该无条件执行
- 希望延迟执行默认值的创建逻辑
《On Java 8》中文版相关知识点
《On Java 8》中文版详细介绍了Optional类的使用方法和设计理念。书中强调,在使用Optional时,应充分理解其方法特性,选择合适的方法以避免性能问题。
书中提到:"Optional的设计目的是为了提供一种更优雅的方式来处理可能为空的值,而不是简单地替代null检查。正确使用Optional的方法,可以使代码更加清晰、健壮。"
总结
orElse和orElseGet的核心区别在于默认值的执行时机:
- orElse无论Optional对象是否为空,都会执行默认值的创建
- orElseGet只有在Optional对象为空时,才会执行默认值的创建
在实际开发中,应根据默认值的创建成本和执行需求,选择合适的方法。对于高成本的默认值创建,优先使用orElseGet以避免不必要的性能损耗。
通过本文的介绍,希望你能更好地理解和使用Optional类的这两个方法,写出更高效、更健壮的Java代码。如果你想深入学习Java 8的更多特性,可以参考《On Java 8》中文版。
交流与学习
如果你在学习《On Java 8》中文版时遇到任何问题,或者想与其他Java开发者交流,可以加入我们的QQ群:
群内有众多Java技术爱好者和专家,可以帮助你解决学习和工作中遇到的问题。
【免费下载链接】OnJava8 《On Java 8》中文版 项目地址: https://gitcode.com/gh_mirrors/on/OnJava8
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




