当前位置: 首页 > news >正文

方法调用时,Java 的及早求值(eager evaluation)策略

问题发现:

在写力扣的 70. 爬楼梯 时,写了如下代码:

classSolution{Map<Integer,Integer>map=newHashMap<>();publicintclimbStairs(intn){if(n<=1){// 边界条件:n == 1或者n == 0return1;}intans=0;ans+=map.getOrDefault(n-1,climbStairs(n-1));//ans+=map.getOrDefault(n-2,climbStairs(n-2));map.put(n,ans);returnans;}}
  • 代码使用 map.getOrDefault 函数,我是想完成如下操作:如果存在 key == n-1 or n-2,就直接将其 value 返回,而不进行递归
  • 但是提交之后一直超时

于是,将代码交给了通义千问,并将问题和原因总结如下:

  • 即使n-1已经在map中,climbStairs(n - 1)仍然会被执行(因为 Java 采用 eager evaluation 策略)
  • 所以不能用getOrDefault来实现记忆化递归

eager evaluation 策略

关于 eager evaluation 策略,也是第一回看到这个词,于是让通义总结了一下:

Java 官方文档和语言规范(Java Language Specification, JLS)明确说明了 Java 采用及早求值(eager evaluation)策略,尤其是在方法调用时对参数的处理。

官方依据:Java 语言规范(JLS)

来源:The Java® Language Specification, Java SE 17 Edition(如下图)

Section 15.12.4. Run-Time Evaluation of Method Invocation下的15.12.4.2. Evaluate Arguments

翻译:

参数表达式(如果有的话)将按照从左到右的顺序依次求值。

这意味着:在真正进入方法体之前,所有传入的参数表达式都必须先被完全求值

举例说明

当写:

map.getOrDefault(key,expensiveComputation());

根据 JLS §15.12.4:

  1. JVM 首先计算key的值;
  2. 然后立即调用expensiveComputation()并等待其返回结果
  3. 最后才调用getOrDefault方法,把这两个已经求好值的结果作为参数传进去。

因此,无论key是否存在于 map 中,expensiveComputation()一定会被执行

补充:对比延迟求值(lazy evaluation)

以 computeIfAbsent 为例,它的签名是:

VcomputeIfAbsent(Kkey,Function<?superK,?extendsV>mappingFunction)

注意:第二个参数是一个函数对象(Function,而不是一个值。

  • 你传入的是一个lambda 表达式,它会被包装成一个Function实例。
  • computeIfAbsent内部决定是否调用mappingFunction.apply(key)
  • 如果 key 已存在,它根本不会调用这个函数 —— 这就是延迟求值(lazy evaluation)的体现。

getOrDefault的签名是:

VgetOrDefault(Objectkey,VdefaultValue)

第二个参数是值类型V,所以调用前必须知道这个值是多少 → 必须提前计算。

关于延迟求值(lazy evaluation) ,可以参考这篇文章:Java的Stream API:惰性求值(Lazy Evaluation)与短路操作的性能优势

参考:

[1] 通义千问

[2] 15.12.4. Run-Time Evaluation of Method Invocation

http://www.gsyq.cn/news/148337.html

相关文章:

  • 2025年AI搜索优化服务市场观察:技术演进与企业适配路径 - 品牌测评鉴赏家
  • 解析 `std::deque` 的‘地图-缓冲区’内存结构:为什么它是实现高性能栈(Stack)的首选底座?
  • 2025 MBA必看!10个降AI率工具测评榜单
  • 软件测试工程师的35岁危机:是确有其事,还是伪命题?
  • 五、定积分
  • 什么是 ‘ABI Breaking’?为什么给 `std::list` 增加一个成员变量会引发整个操作系统的崩溃风险?
  • 第六次团队作业-事后分析部分
  • 孩子想学人工智能?2025年高口碑机构选课攻略来了 - 品牌测评鉴赏家
  • 解析 C++20 `std::ranges` 管道符:如何利用延迟求值(Lazy Evaluation)处理无限序列?
  • 解析 ‘Flyweight Pattern’:在高频交易系统中如何共享千万级订单数据的元信息?
  • 第六次团队作业——事后分析部分
  • 2025年市面上专业的换热器公司哪家靠谱,工业型暖风机/侧吹风幕机/空气换热器/工业风幕机,换热器品牌排行 - 品牌推荐师
  • 互联网大厂Java面试:从Spring Boot到微服务架构的场景应用
  • 完整教程:openGauss在AI时代的向量数据库应用实践与技术演进深度解析
  • 基于链动2+1模式、AI智能名片与S2B2C商城小程序的粉丝社群策划与实施研究
  • AI时代流量密码:揭秘顶尖搜索排名优化公司 - 品牌测评鉴赏家
  • 河南保护膜标杆企业!众思创PE_铝天花保护膜赋能建材产业 - 朴素的承诺
  • 12312
  • 2025权威发布!新加坡留学中介服务实力榜单揭晓 - 留学品牌推荐官
  • 工业嵌入式系统串行接口:技术演进、核心优势与选型指南
  • 第六次团队作业-复审部分
  • 哈希-03-字母异位词分组
  • 教育博主实测:2025年高性价比AI智能体开发服务推荐指南 - 品牌测评鉴赏家
  • PyTorch MNIST全连接分类器完整流程
  • 深入解析:基于Spring Boot 3 + Spring Security6 + JWT + Redis实现登录、token身份认证
  • 一些Android平台的早期J2ME实现方案的情况
  • 揭秘沃尔玛购物卡回收猫腻,教你安全避坑 - 京顺回收
  • 2025最新!10个AI论文平台测评:研究生写论文必备神器
  • 国内混合机五大头部厂商实力比拼!探寻优质搅拌机设备的技术突破与服务特色 - 速递信息
  • 2025年终母线桥厂家权威推荐:母线/母线槽全品类产品资讯速递 - 深度智识库