如何使用 CompletableFuture、Function 和 Optional 优雅地处理异步编程?

news2025/4/25 6:21:31

当异步遇上函数式编程,代码变得更优雅

在日常开发中,很多时候我们需要处理异步任务、函数转换和空值检查。传统的回调方式和空值判断常常让代码看起来繁琐而难以维护。幸运的是,Java 提供了 CompletableFutureFunctionOptional,这三个工具能够帮助我们以更简洁、更优雅的方式处理这些常见问题。

今天,我们将深入探讨如何利用这三者的组合来编写既清晰又高效的代码。通过简单的示例,我们一起看一下这三者是如何协作的,如何让我们远离冗长的 null 检查,告别复杂的回调地狱,并让我们的异步任务更加易于理解。


一、CompletableFuture:异步编程的利器

CompletableFuture 是 Java 8 引入的用于处理异步操作的类。它的出现让我们告别了传统的基于回调的异步编程模式。通过 CompletableFuture,我们可以以更声明式的方式处理并发任务,将复杂的任务流写得更清晰。

我们来看看一个简单的 CompletableFuture 示例:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    return 1 + 1;
});

future.thenAccept(result -> System.out.println("The result is: " + result));

在这个例子中,supplyAsync 方法启动了一个异步任务,计算了 1 + 1,然后通过 thenAccept 处理返回的结果。最重要的是,CompletableFuture 并不阻塞主线程,它允许我们在等待异步结果时继续执行其他操作。

为什么它重要:

CompletableFuture 可以显著提高程序的并发性和可读性,让异步编程变得像同步编程一样简单。它还提供了丰富的操作符(如 thenApplythenCombine 等),让任务的组合更加灵活。


二、Function:让数据转化变得轻松

Function 接口是 Java 8 引入的一个函数式接口,它能够将一个输入转化为一个输出。它常用于数据转换、函数组合等场景。

例如,我们可以通过 Function 将一个字符串转换为大写:

Function<String, String> toUpperCase = str -> str.toUpperCase();
System.out.println(toUpperCase.apply("hello"));  // 输出 "HELLO"
为什么它重要:

Function 可以帮助我们对数据进行转换,并且支持链式调用。我们可以通过 andThencompose 方法将多个转换操作连接起来,从而避免了冗长的嵌套逻辑。


三、Optional:避免 NPE(空指针异常)的利器

Optional 是 Java 8 引入的容器类,用来处理可能为空的值。它通过显式地包装值,帮助我们避免显式的 null 检查,从而让代码更加清晰、易于维护。

例如,下面是一个简单的 Optional 使用示例:

Optional<String> name = Optional.ofNullable(null);
name.ifPresent(n -> System.out.println("Hello, " + n));  // 什么也不做,因为值为 null
为什么它重要:

Optional 是防止空指针异常的良方。通过 isPresentmapflatMap 等方法,我们可以优雅地处理可能为 null 的值,而不是使用冗长的 null 检查。


四、CompletableFuture、Function 和 Optional 的组合:打造优雅的异步编程

现在,我们来结合这三者,构建一个复杂的异步场景。假设我们有一个订单查询系统,用户查询订单信息时,可能会遇到以下问题:

  • 查询结果可能为空。
  • 查询结果可能需要进一步处理(例如获取订单详情、计算总价等)。

我们通过 CompletableFuture 异步执行查询任务,利用 Function 对数据进行转换,同时通过 Optional 处理可能为 null 的情况。

场景:查询用户订单并计算订单总价
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

public class OrderProcessing {

    // 模拟查询订单信息的异步方法
    public static CompletableFuture<Optional<Order>> getOrderAsync(String orderId) {
        return CompletableFuture.supplyAsync(() -> {
            // 模拟查询过程
            if ("123".equals(orderId)) {
                return Optional.of(new Order(orderId, 100));
            } else {
                return Optional.empty();
            }
        });
    }

    // 使用 Function 处理订单信息
    public static Function<Order, Double> calculateTotalPrice = order -> order.getAmount() * 1.1; // 计算总价,加上 10% 税费

    public static void main(String[] args) {
        String orderId = "123";

        getOrderAsync(orderId)
            .thenApply(orderOptional -> orderOptional.map(calculateTotalPrice))
            .thenAccept(totalPriceOpt -> 
                totalPriceOpt.ifPresentOrElse(
                    price -> System.out.println("订单总价是:" + price),
                    () -> System.out.println("订单未找到")
                )
            );
    }

    // 订单类
    static class Order {
        private String id;
        private double amount;

        public Order(String id, double amount) {
            this.id = id;
            this.amount = amount;
        }

        public double getAmount() {
            return amount;
        }
    }
}
解析:
  1. getOrderAsync:使用 CompletableFuture.supplyAsync() 异步查询订单。返回一个 Optional<Order>,避免了 null 的问题。
  2. calculateTotalPrice:使用 Function 对订单金额进行计算,将税费加成到总价中。
  3. thenApplymap:首先,我们用 thenApply 将订单处理成 Optional<Double> 类型,处理完的结果是订单总价(如果订单存在)。
  4. ifPresentOrElse:最后,我们使用 ifPresentOrElse 判断总价是否存在,若存在则打印出来,否则输出“订单未找到”。

五、总结:

通过结合 CompletableFutureFunctionOptional,我们可以更简洁、优雅地处理复杂的异步编程场景。这样做不仅提升了代码的可读性,还避免了常见的异常问题(如空指针异常)。这三者各自发挥着作用,但结合使用时能够发挥出最大的效能,让我们在开发过程中,既能提升生产力,又能减少潜在的错误。

  • CompletableFuture:让异步任务处理变得更加简单直观。
  • Function:帮助我们进行函数式数据转换和处理。
  • Optional:避免了空指针异常,使代码更安全、健壮。

这就是 CompletableFutureFunctionOptional 的强大组合,掌握它们,你就能写出更加优雅的 Java 代码!

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 什么是 Cookie?简单介绍与使用方法

  • 什么是 Session?如何应用?

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • 如何理解应用 Java 多线程与并发编程?

  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 如何理解线程安全这个概念?

  • 理解 Java 桥接方法

  • Spring 整合嵌入式 Tomcat 容器

  • Tomcat 如何加载 SpringMVC 组件

  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”

  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”

  • Java 中消除 If-else 技巧总结

  • 线程池的核心参数配置(仅供参考)

  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)

  • Java 枚举的几个常用技巧,你可以试着用用

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • 探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)

  • 为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2342189.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

操作系统概述与安装

主流操作系统概述 信创平台概述 虚拟机软件介绍与安装 windows server 安装 centos7 安装 银河麒麟V10 安装 一&#xff1a;主流服务器操作系统 &#xff08;1&#xff09;Windows Server 发展历程&#xff1a; 1993年推出第一代 WindowsNT&#xff08;企业级内核&am…

开发了一个b站视频音频提取器

B站资源提取器-说明书 一、功能说明 本程序可自动解密并提取B站客户端缓存的视频资源&#xff0c;支持以下功能&#xff1a; - 自动识别视频缓存目录 - 将加密的.m4s音频文件转换为标准MP3格式 - 将加密的.m4s视频文件转换为标准MP4格式&#xff08;合并音视频流&#xff09;…

基于javaweb的SpringBoot校园服务平台系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

PHYBench:首个大规模物理场景下的复杂推理能力评估基准

2025-04-23, 由北京大学物理学院和人工智能研究所等机构共同创建的 PHYBench 数据集&#xff0c;这是一个专门用于评估大型语言模型在物理场景下的复杂推理能力的高质量基准。该数据集包含 500 道精心策划的物理问题&#xff0c;覆盖力学、电磁学、热力学、光学、现代物理和高级…

Red:1靶场环境部署及其渗透测试笔记(Vulnhub )

环境介绍&#xff1a; 靶机下载&#xff1a; https://download.vulnhub.com/red/Red.ova 本次实验的环境需要用到VirtualBox&#xff08;桥接网卡&#xff09;&#xff0c;VMware&#xff08;桥接网卡&#xff09;两台虚拟机&#xff08;网段都在192.168.152.0/24&#xff0…

深入详解人工智能数学基础——概率论中的KL散度在变分自编码器中的应用

🧑 博主简介:CSDN博客专家、CSDN平台优质创作者,高级开发工程师,数学专业,10年以上C/C++, C#, Java等多种编程语言开发经验,拥有高级工程师证书;擅长C/C++、C#等开发语言,熟悉Java常用开发技术,能熟练应用常用数据库SQL server,Oracle,mysql,postgresql等进行开发应用…

测试模版x

本篇技术博文摘要 &#x1f31f; 引言 &#x1f4d8; 在这个变幻莫测、快速发展的技术时代&#xff0c;与时俱进是每个IT工程师的必修课。我是盛透侧视攻城狮&#xff0c;一名什么都会一丢丢的网络安全工程师&#xff0c;也是众多技术社区的活跃成员以及多家大厂官方认可人员&a…

Openharmony 和 HarmonyOS 区别?

文章目录 OpenHarmony 与 HarmonyOS 的区别&#xff1a;开源生态与商业发行版的定位差异一、定义与定位二、技术架构对比1. OpenHarmony2. HarmonyOS 三、应用场景差异四、开发主体与生态支持五、关键区别总结六、如何选择&#xff1f;未来展望 OpenHarmony 与 HarmonyOS 的区别…

uniapp 仿小红书轮播图效果

通过对小红书的轮播图分析&#xff0c;可得出以下总结&#xff1a; 1.单张图片时容器根据图片像素定高 2.多图时轮播图容器高度以首图为锚点 3.比首图长则固高左右留白 4.比首图短则固宽上下留白 代码如下&#xff1a; <template><view> <!--轮播--><s…

R/G-B/G色温坐标系下对横纵坐标取对数的优势

有些白平衡色温坐标系会分别对横纵坐标取对数运算。 这样做有什么优势呢? 我们知道对数函数对0-1之间的因变量值具有扩展作用。即自变量x变化比较小时,经过对数函数作用后可以把因变量扩展到较大范围内,即x变化较小时,y变化较大,增加了识别数据的识别性。 由于Raw数据中的…

AI赋能安全调度系统:智能升级与功能跃迁

安全调度系统通过AI技术的深度整合&#xff0c;实现了从传统监控到智能决策的质变升级。这种智能化转型不仅提升了系统的响应速度和处理精度&#xff0c;更重塑了整个安全管理的运行范式。以下是AI技术为安全调度系统带来的核心功能强化&#xff1a; 智能风险识别与预警能力跃…

数据结构与算法(十二):图的应用-最小生成树-Prim/Kruskal

相关文献&#xff1a; 数据结构与算法(一)&#xff1a;基础理论 数据结构与算法(二)&#xff1a;线性表的实现 数据结构与算法(三)&#xff1a;线性表算法设计练习 数据结构与算法(四)&#xff1a;斐波那契数列 数据结构与算法(五)&#xff1a;LRU 数据结构与算法(六)&#xff…

项目——高并发内存池

目录 项目介绍 做的是什么 要求 内存池介绍 池化技术 内存池 解决的问题 设计定长内存池 高并发内存池整体框架设计 ThreadCache ThreadCache整体设计 哈希桶映射对齐规则 ThreadCache TLS无锁访问 CentralCache CentralCache整体设计 CentralCache结构设计 C…

系统与网络安全------弹性交换网络(2)

资料整理于网络资料、书本资料、AI&#xff0c;仅供个人学习参考。 Eth-Trunk 组网中经常会遇到的问题 链路聚合技术 概述 Eth-Trunk&#xff08;链路聚合技术&#xff09;作为一种捆绑技术&#xff0c;可以把多个独立的物理接口绑定在一起&#xff0c;作为一个大带宽的逻辑…

信息系统项目管理工程师备考计算类真题讲解八

一、风险管理 示例1&#xff1a;EMV 解析&#xff1a;EMV(Expected Monetary Value)预期货币价值。一种定量风险分析技术。通过考虑各种风险事件的概率及其可能带来的货币影响&#xff0c;来计算项目的预期价值。 可以用下面的较长进行表示&#xff1a; 水路的EMV:7000*3/4(7…

优化uniappx页面性能,处理页面滑动卡顿问题

问题&#xff1a;在页面遇到滑动特别卡的情况就是在页面使用了动态样式或者动态类&#xff0c;做切换的时候页面重新渲染导致页面滑动卡顿 解决&#xff1a;把动态样式和动态类做的样式切换改为通过获取元素修改样式属性值 循环修改样式示例 bannerList.forEach((_, index)…

【玩转全栈】—— 无敌前端究极动态组件库--Inspira UI

目录 Inspira UI 介绍 配置环境 使用示例 效果&#xff1a; Inspira UI 学习视频&#xff1a; 华丽优雅 | Inspira UI快速上手_哔哩哔哩_bilibili 官网&#xff1a;https://inspira-ui.com/ Inspira UI 介绍 Inspira UI 是一个设计精美、功能丰富的用户界面库&#xff0c;专为…

《求知导刊》是CN期刊吗?学术期刊吗?

《求知导刊》是CN 期刊&#xff0c;同时也属于学术期刊。 CN 期刊的定义 CN 期刊是指在我国境内注册、经国家新闻出版署批准公开发行的期刊&#xff0c;具备国内统一连续出版物号&#xff08;CN 号&#xff09;。这是判断期刊是否为正规合法期刊的重要标准。 《求知导刊》的 C…

动手试一试 Spring Security入门

1.创建Spring Boot项目 引入Web和Thymeleaf的依赖启动器 2.引入页面Html资源文件 在项目的resources下templates目录中&#xff0c;引入案例所需的资源文件&#xff08;下载地址&#xff09;&#xff0c;项目结构如下 3.创建控制器 Controller public class FilmController…

使用若依二次开发商城系统-4:商品属性

功能3&#xff1a;商品分类 功能2&#xff1a;商品品牌 功能1&#xff1a;搭建若依运行环境前言 商品属性功能类似若依自带的字典管理&#xff0c;分两步&#xff0c;先设置属性名&#xff0c;再设置对应的属性值。 一.操作步骤 1&#xff09;数据库表product_property和pro…