Java 中Supplier延迟生成值的原因

news2025/5/20 9:43:47

在编程中,延迟生成值(Lazy Value Generation) 是指将值的计算或生成过程推迟到真正需要使用该值时才执行。这一机制的核心是避免不必要的计算,提升程序的性能和资源利用率。结合 SupplierOptional 的使用场景,我们可以从以下几个方面理解延迟生成值:

一、核心概念:为什么需要延迟?

假设你需要一个默认值,但这个默认值的生成可能:

  • 耗时(如数据库查询、网络请求)。
  • 耗资源(如创建大型对象、复杂计算)。
  • 依赖状态(如需要先判断某个条件是否成立)。

如果提前生成默认值,可能会导致:

  • 性能浪费:即使最终不需要使用默认值(比如 Optional 中有值),也会白白执行计算。
  • 逻辑错误:默认值的生成可能依赖后续才会变化的状态。

延迟生成的目标:仅在必要时执行计算,减少无意义的开销。

二、通过 Supplier 实现延迟生成

Supplier 是 Java 函数式接口(@FunctionalInterface),仅定义一个无参数方法 get(),用于返回一个值。它的关键作用是:将值的生成逻辑封装在 get(),而不立即执行。

示例:模拟耗时操作
import java.util.Optional;
import java.util.UUID;

public class LazyDemo {
    public static void main(String[] args) {
        Optional<String> optional = Optional.empty(); // 假设无值

        // 错误写法:提前执行生成逻辑(无论是否需要)
        String eagerValue = generateEagerly(); // 立即执行
        String value1 = optional.orElse(eagerValue); 

        // 正确写法:延迟执行生成逻辑(仅在必要时)
        String value2 = optional.orElseGet(() -> generateLazily()); // 仅当optional为空时执行
    }

    // 提前生成(立即执行)
    private static String generateEagerly() {
        System.out.println("执行提前生成逻辑");
        return UUID.randomUUID().toString();
    }

    // 延迟生成(通过Supplier封装)
    private static String generateLazily() {
        System.out.println("执行延迟生成逻辑");
        return UUID.randomUUID().toString();
    }
}
执行结果对比
  • optional 为空时:
    • generateEagerly() 会在调用 orElse 前就执行,输出 执行提前生成逻辑
    • generateLazily() 仅在调用 orElseGetoptional 为空时执行,输出 执行延迟生成逻辑
  • optional 有值时(如 Optional.of("有值")):
    • generateEagerly() 仍然会执行(浪费计算)。
    • generateLazily() 不会执行(节省资源)。

三、延迟生成的典型应用场景

1. 避免不必要的计算
// 假设getExpensiveData()是耗时操作
Optional<String> data = fetchData(); 

// 错误:无论data是否有值,都会执行getExpensiveData()
String result = data.orElse(getExpensiveData()); 

// 正确:仅当data为空时,才执行getExpensiveData()
String result = data.orElseGet(() -> getExpensiveData()); 
2. 依赖上下文的动态默认值
public class UserService {
    private final Database database;

    public User getUser(String userId) {
        Optional<User> user = database.queryUser(userId);
        // 仅当用户不存在时,创建默认用户(依赖当前时间)
        return user.orElseGet(() -> createDefaultUser(LocalDateTime.now()));
    }

    private User createDefaultUser(LocalDateTime timestamp) {
        // 需要当前时间作为参数,延迟生成时才能获取最新值
        return new User("default", timestamp);
    }
}
  • 如果提前生成默认用户(如 orElse(createDefaultUser(...))),可能使用过时的时间戳。
  • 延迟生成时,createDefaultUser 能获取当前最新的上下文数据(如实时时间)。
3. 流式编程中的延迟计算

在 Java Stream 中,某些操作(如 filtermap)是惰性的(Lazy),仅在终端操作(如 forEachcollect)时才执行。Supplier 可以配合这种特性优化性能:

List<String> data = ...;

// 延迟生成随机数,仅在需要时(如过滤后的数据满足条件)才生成
data.stream()
    .filter(s -> s.startsWith("A"))
    .findFirst()
    .orElseGet(() -> UUID.randomUUID().toString()); // 仅当无匹配元素时生成

四、延迟生成与立即生成的对比

场景延迟生成(orElseGet立即生成(orElse
性能仅在必要时执行计算,节省资源无论是否需要,均提前执行计算
适用场景默认值生成耗时、依赖动态状态默认值已提前存在或生成成本极低
代码可读性需通过 lambda 封装逻辑,稍显复杂直接传入值,代码更简洁
线程安全性每次调用 get() 都会重新计算(需注意)提前生成一次,后续使用同一值

五、总结:延迟生成的本质

延迟生成值的核心是将计算逻辑与值的使用时机解耦,通过 Supplier 等工具将 “生成值” 的动作推迟到真正需要的时刻。这一思想在 Java 中广泛应用于:

  • Optional 的默认值生成(orElseGet)。
  • 流式编程的惰性操作。
  • 框架中的依赖注入(如 Spring 的 Lazy 注解)。
  • 缓存场景的按需加载(如 ConcurrentHashMap.computeIfAbsent)。

通过延迟生成,可以显著提升程序的效率,避免 “过早计算” 带来的性能损耗,尤其在处理高成本操作或动态依赖时优势明显。

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

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

相关文章

Web 技术与 Nginx 网站环境部署

这里写目录标题 一. Web基础域名和DNS域名的概念域名的结构域名结构类型 Hosts文件Hosts文件的作用修改Hosts文件 DNS域名注册 网页与HTML网页概述HTML概述HTML基本标签HTML语法规则HTML文件结构 网站和主页Web1.0 与 Web2.0 静态网页与动态网页静态网页动态网页动态网页语言 H…

FP8精度革命:Hopper架构下大模型训练的误差传播控制方法

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;H卡级别算力&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生专属优惠。 一、FP8为何成为大模型训练的新范式&#xff1f; 1.1 算力需求与精度演进的矛盾 当前大语言…

手动制做一个Transformer

本文来自I made a transformer by hand . 一直以来&#xff0c;笔者对 transformer 的注意力机制、qkv的理解都浮于表面&#xff0c;当然也不是说我看完 I made a transformer by hand 后理解有多深入&#xff0c;但确实加深了我对相关概念的理解&#xff0c;故搬运此文章&…

已解决——如何让网站实现HTTPS访问?

一、申请SSL证书 SSL证书是HTTPS实现的关键&#xff0c;它由受信任的证书颁发机构&#xff08;CA&#xff09;签发&#xff0c;用于验证网站的身份并加密数据传输。以下是申请SSL证书的常见步骤&#xff1a; 选择证书类型 根据网站的需求和预算&#xff0c;选择合适的SSL证书…

WebRTC技术EasyRTC嵌入式音视频通信SDK助力智能电视搭建沉浸式实时音视频交互

一、方案概述​ EasyRTC是一款基于WebRTC技术的开源实时音视频通信解决方案&#xff0c;具备低延迟、高画质、跨平台等优势。将EasyRTC功能应用于智能电视&#xff0c;能够为用户带来全新的交互体验&#xff0c;满足智能电视在家庭娱乐、远程教育、远程办公、远程医疗等多种场…

小乌龟git中的推送账户、作者账户信息修改

文章目录 修改git文档作者信息修改git推送用户信息参考文献 修改git文档作者信息 小乌龟中的用户信息为&#xff1a;作者信息&#xff0c;并非推送用户。 上边用户信息&#xff0c;修改的是文件的作者信息。如果想要修改git服务中记录的推送用户信息需要修改推送用户信息。 …

Kubernetes MCP服务器(K8s MCP):如何使用?

#作者&#xff1a;曹付江 文章目录 1、什么是 Kubernetes MCP 服务器&#xff1f;1.1、K8s MCP 服务器 2、开始前的准备工作2.1. Kubernetes集群2.2. 安装并运行 kubectl2.3. Node.js 和 Bun2.4. &#xff08;可选&#xff09;Helm v3 3、如何设置 K8s MCP 服务器3.1. 克隆存储…

R²AIN SUITE 亮相第九届智能工厂高峰论坛

2025年5月16日&#xff0c;在圆满落幕的第九届智能工厂高峰论坛上&#xff0c;上海比孚信息科技有限公司携自主研发的 RAIN SUITE 企业AI应用中台解决方案亮相展会。本次论坛以"从互联工厂到智慧工厂"为主题&#xff0c;吸引了400余位行业专家、制造企业代表及产业链…

深入理解仿函数(Functors):从概念到实践

文章目录 1. 什么是仿函数&#xff1f;2. 仿函数与普通函数的区别3. 标准库中的仿函数4. 仿函数的优势4.1 状态保持4.2 可定制性4.3 性能优势 5. 现代C中的仿函数5.1 Lambda表达式5.2 通用仿函数 6. 仿函数的高级应用&#xff08;使用C2020标准库及以上版本&#xff09;6.1 函数…

InternLM 论文分类微调实践(XTuner 版)

1.环境安装 我创建开发机选择镜像为Cuda12.2-conda&#xff0c;选择GPU为100%A100的资源配置 Conda 管理环境 conda create -n xtuner_101 python3.10 -y conda activate xtuner_101 pip install torch2.4.0cu121 torchvision torchaudio --extra-index-url https://downloa…

PC:使用WinSCP密钥文件连接sftp服务器

1. 打开winscp工具&#xff0c;点击“标签页”->“新标签页” 2. 点击“高级"->“高级” 3. 点击"验证"->“选择密钥文件” 选择ppk文件&#xff0c;如果没有ppk文件选择pem文件&#xff0c;会自动生成ppk文件 点击确定 4. 输入要连接到的sftp服务器的…

1688正式出海,1688跨境寻源通接口接入,守卫的是国内工厂资源

在1688平台的跨境招商直播中&#xff0c;许多想要进入跨境市场的初学者商家纷纷提问&#xff1a;货通全球的入口在哪里&#xff1f;小白商家应该如何操作&#xff1f;商品为何上传失败&#xff1f; 从表面上看&#xff0c;这似乎是1688平台在拓展海外市场的一次积极“进攻”。…

力扣303 区域和检索 - 数组不可变

文章目录 题目介绍题解 题目介绍 题解 不用管第一个null&#xff0c;从第二个开始看就可以 法一&#xff1a;暴力解法 class NumArray {private int[] nums;public NumArray(int[] nums) {this.nums nums;}public int sumRange(int left, int right) {int res 0;for (int i…

Spring的后置处理器是干什么用的?扩展点又是什么?

Spring 的后置处理器和扩展点是其框架设计的核心机制&#xff0c;它们为开发者提供了灵活的扩展能力&#xff0c;允许在 Bean 的生命周期和容器初始化过程中注入自定义逻辑。 1. 后置处理器&#xff08;Post Processors&#xff09; 后置处理器是 Spring 中用于干预 Bean 生命…

[ linux-系统 ] 进程地址空间

验证地址空间 父子进程的变量值不同但是地址相同&#xff0c;说明该地址绝对不是物理地址 我们叫这种地址为虚拟地址/线性地址 分析与结论 上述实验表明&#xff0c;父子进程的变量地址相同但内容不同&#xff0c;说明地址为虚拟地址&#xff0c;且父子进程有各自独立的物理…

文件名是 ‪E:\20250512_191204.mp4, EV软件录屏,未保存直接关机损坏, 如何修复?

去github上下载untrunc 工具就能修复 https://github.com/anthwlock/untrunc/releases 如果访问不了 本机的 hosts文件设置 140.82.112.3 github.com 199.232.69.194 github.global.ssl.fastly.net 就能访问了 实在不行&#xff0c;从这里下载&#xff0c;传上去了 https://do…

Java常见API文档(下)

格式化的时间形式的常用模式对应关系如下&#xff1a; 空参构造创造simdateformate对象&#xff0c;默认格式 练习.按照指定格式展示 package kl002;import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date;public class Date3 {publi…

DRIVEGPT4: 通过大语言模型实现可解释的端到端自动驾驶

《DriveGPT4: Interpretable End-to-End Autonomous Driving via Large Language Model》 2024年10月发表&#xff0c;来自香港大学、浙江大学、华为和悉尼大学。 多模态大型语言模型&#xff08;MLLM&#xff09;已成为研究界关注的一个突出领域&#xff0c;因为它们擅长处理…

构建共有语料库 - Wiki 语料库

中文Wiki语料库主要指的是从中文Wikipedia&#xff08;中文维基百科&#xff09;提取的文本数据。维基百科是一个自由的、开放编辑的百科全书项目&#xff0c;覆盖了从科技、历史到文化、艺术等广泛的主题。 对于基于RAG的应用来说&#xff0c;把Wiki语料作为一个公有的语料库…

苍穹外卖项目中的 WebSocket 实战:实现来单与催单提醒功能

&#x1f680; 苍穹外卖项目中的 WebSocket 实战&#xff1a;实现来单与催单提醒功能 在现代 Web 应用中&#xff0c;实时通信成为提升用户体验的关键技术之一。WebSocket 作为一种在单个 TCP 连接上进行全双工通信的协议&#xff0c;被广泛应用于需要实时数据交换的场景&#…