Java 8 Optional.orElse与orElseGet区别:《On Java 8》中文版性能陷阱

Java 8 Optional.orElse与orElseGet区别:《On Java 8》中文版性能陷阱

【免费下载链接】OnJava8 《On Java 8》中文版 【免费下载链接】OnJava8 项目地址: 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的场景

  1. 默认值是简单对象或基本类型
  2. 默认值的创建成本非常低
  3. 无论Optional是否为空,都需要执行默认值的创建逻辑

使用orElseGet的场景

  1. 默认值的创建成本较高
  2. 默认值的创建有副作用,不应该无条件执行
  3. 希望延迟执行默认值的创建逻辑

《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技术交流群

群内有众多Java技术爱好者和专家,可以帮助你解决学习和工作中遇到的问题。

【免费下载链接】OnJava8 《On Java 8》中文版 【免费下载链接】OnJava8 项目地址: https://gitcode.com/gh_mirrors/on/OnJava8

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值