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

lambda表达式练习案例

前言

在Java 8问世之前,我们如果想给某个方法传入一段"行为",只能通过匿名内部类来实现——创建一个接口的匿名实现对象,然后在里面覆盖方法。这种写法虽然能完成任务,但代码臃肿、可读性差,充斥着大量与核心逻辑无关的样板代码。

Lambda表达式的出现,正是为了解决这个问题。它让我们可以用极其简洁的语法来表达"行为",把注意力从"对象"转移到"操作"本身。

本文通过"两数之和"和"找出偶数"两个实战练习,从匿名内部类写法逐步过渡到Lambda表达式写法,在对比中带你理解:

  • Lambda到底简化了什么?

  • 为什么它能这样简化?

  • 什么情况下能用Lambda,什么情况下不行?

一步步揭开Lambda表达式背后的设计思想和适用边界。

摘要

本文通过两个实战练习,系统讲解Lambda表达式如何优化匿名内部类的冗余写法。首先在"两数之和"和"找出偶数"练习中,分别展示匿名内部类与Lambda两种实现方式的代码对比,直观呈现Lambda在代码量上的简化效果。进而深入分析简化的本质原因:Lambda只能替换函数式接口(即只有一个抽象方法的接口)的匿名内部类,因为它省略了对象创建、方法名声明、参数类型、返回值类型等所有编译器可推断的冗余信息,只保留核心操作逻辑。文章进一步总结Lambda的三个简化层次和适用前提条件,并指出这种写法背后是从"面向对象"到"面向行为"的思维转变。最后通过延伸思考引导读者继续深入学习自定义函数式接口、Stream流式编程和方法引用等进阶内容。

目录

一、练习1:两数之和

匿名内部类写法

优化为lambda表达式

二、练习2:找出偶数

匿名内部类写法

优化为lambda表达式

思考:lambda是如何优化匿名内部类写法的?

1. 从两个练习中找规律

2. 什么是函数式接口?

3. Lambda为什么能替换匿名内部类?

4. 从面向对象到面向行为的思维转变

5. Lambda的三个简化层次

6. 使用Lambda的前提条件

7. 延伸思考


一、练习1:两数之和

匿名内部类写法

public class Main { public static void main(String[] args) { //直接调用方法,获取结果 int i = calculateNum(new IntBinaryOperator() { @Override public int applyAsInt(int left, int right) { return left + right; } }); //打印结果 System.out.println("计算结果:" + i); } //定义一个静态方法,接收一个IntBinaryOperator参数(该参数本质是一个jdk自带的接口) public static int calculateNum(IntBinaryOperator operator){ int a = 10; int b = 20; //返回a+b的和 return operator.applyAsInt(a, b); } }

运行结果如下:

注意:

  • 上面静态方法的参数,是jdk自带的一个接口,它既然要求接收一个该类型的接口,那我们直接创建一个接口(并实现了下面的applyAsInt方法)传进去即可。
  • 不难发现,该接口下面,只有一个方法,这就叫“函数式接口”。这也是能进行lambda优化的最关键一点。

优化为lambda表达式

public class Main { public static void main(String[] args) { //直接调用方法,获取结果 int i = calculateNum((int left, int right)-> { return left + right; }); //打印结果 System.out.println("计算结果:" + i); } //定义一个静态方法,接收一个IntBinaryOperator参数(该参数本质是一个jdk自带的接口) public static int calculateNum(IntBinaryOperator operator){ int a = 10; int b = 20; //返回a+b的和 return operator.applyAsInt(a, b); } }

二、练习2:找出偶数

匿名内部类写法

public class Main { public static void main(String[] args) { //调用静态方法 printNum(new IntPredicate() { @Override public boolean test(int value) { return value%2==0;//定标准:偶数则返回true,奇数则返回false } }); } //定义一个静态方法,接收一个IntPredicate参数(该参数本质是一个jdk自带的接口) public static void printNum(IntPredicate predicate){ int[] arr = {1,2,3,4,5,6,7,8,9}; //筛选出arr中,符合要求的数字 for(int i: arr){ if(predicate.test(i)){ System.out.println(i);//打印出符合要求的数字 } } } }

运行结果如下:

优化为lambda表达式

public class Main { public static void main(String[] args) { //调用静态方法 printNum((int value) -> { return value%2==0;//定标准:偶数则返回true,奇数则返回false }); } //定义一个静态方法,接收一个IntPredicate参数(该参数本质是一个jdk自带的接口) public static void printNum(IntPredicate predicate){ int[] arr = {1,2,3,4,5,6,7,8,9}; //筛选出arr中,符合要求的数字 for(int i: arr){ if(predicate.test(i)){ System.out.println(i);//打印出符合要求的数字 } } } }

运行结果如下:

思考:lambda是如何优化匿名内部类写法的?

通过上面两个练习的对比,我们直观地感受到了Lambda表达式带来的代码简化。但作为学习者,我们不能只停留在"会用"的层面,更要理解它为什么能这样简化,以及简化的边界在哪里

1. 从两个练习中找规律

回顾练习1和练习2,你会发现一个共同点:

练习1练习2
自定义方法形参IntBinaryOperator operatorIntPredicate predicate
形参类型接口接口
接口抽象方法int applyAsInt(int left, int right)boolean test(int value)
匿名内部类写法new IntBinaryOperator() { ... }new IntPredicate() { ... }
Lambda写法(left, right) -> left + rightvalue -> value % 2 == 0

规律很清晰:当方法的形参是一个接口时,我们就可以用Lambda表达式来简化传参。

但这里有一个更精确的结论——不是所有接口都可以用Lambda替换,只有"函数式接口"才行。

2. 什么是函数式接口?

函数式接口,简单来说就是只有一个抽象方法的接口

  • IntBinaryOperator:只有一个抽象方法applyAsInt

  • IntPredicate:只有一个抽象方法test

这两个都是JDK自带的函数式接口,它们都标记了一个注解@FunctionalInterface(这个注解不是必须的,但加上后编译器会帮你检查是否只有一个抽象方法)。

注意:接口中可以存在多个方法,但只要抽象方法只有一个,它就是函数式接口。默认方法(default修饰)和静态方法不影响。

3. Lambda为什么能替换匿名内部类?

我们来剖析一下匿名内部类的写法:

new IntBinaryOperator() { @Override public int applyAsInt(int left, int right) { return left + right; } }

这段代码包含了哪些信息?

  1. 对象创建new IntBinaryOperator() { ... }—— 创建一个接口的匿名实现类对象

  2. 方法声明public int applyAsInt(int left, int right)—— 方法名、返回值、参数列表

  3. 方法体return left + right;—— 真正的业务逻辑

而Lambda表达式只写了什么?

(left, right) -> left + right

Lambda把冗余信息全部省略了:

被省略的内容原因
new 接口名() { ... }编译器知道这里需要一个接口的实现,不需要显式new
方法名applyAsInt接口只有一个抽象方法,默认就是实现它,无需指名
返回值类型int编译器能从上下文推断出返回int
参数类型int编译器能从接口方法定义推断出参数类型
{}return只有单条语句时可以省略
()只有一个参数时可以省略

总结一句话:Lambda表达式关注的是"做什么",而把"谁来做""怎么做声明"全部交给编译器去推断。

4. 从面向对象到面向行为的思维转变

这是理解Lambda最核心的一点。

匿名内部类的思维方式

"我需要创建一个接口的实现对象,这个对象里要覆盖那个抽象方法,方法里写具体的操作。"

这是一种"先造人,再让人干活"的面向对象思维。

Lambda的思维方式

"我需要一个操作,这个操作接收这些数据,返回那个结果。"

这是一种"直接描述动作"的函数式思维。

用生活中的例子来类比:

  • 匿名内部类就像:你点餐时,餐厅给你一个厨师(对象),让他去做菜(方法)。

  • Lambda表达式就像:你直接说"我要一份番茄炒蛋"(行为本身),不需要关心是谁做的。

5. Lambda的三个简化层次

从练习中,我们可以总结出Lambda的三个简化层级:

第一层:完整写法(省略new和接口名)

(int left, int right) -> { return left + right; }

第二层:省略参数类型(编译器推断)

(left, right) -> { return left + right; }

第三层:省略花括号、return和分号(单条语句时)

(left, right) -> left + right

对于单参数的情况,还可以省略小括号:

value -> value % 2 == 0 // 而不是 (value) -> value % 2 == 0

6. 使用Lambda的前提条件

我们最后总结一下,使用Lambda替换匿名内部类需要满足的条件:

条件说明
① 接口类型方法的形参必须是接口,不能是抽象类或普通类
② 函数式接口该接口只能有一个抽象方法
③ 上下文明确编译器能推断出目标类型(即接口类型)

特别注意:如果接口有多个抽象方法,就无法用Lambda,因为编译器不知道你要实现的是哪一个。这时候只能继续用匿名内部类。

7. 延伸思考

学到这里,你可能会想:

  • 如果我想自己定义一个这样的接口,该怎么写?

  • 除了替换匿名内部类,Lambda还能用在什么地方?

  • ::这个写法又是什么?

这些问题我们留到后续文章继续探讨。但无论如何,请记住今天的核心收获:

Lambda表达式的本质,是从"创建对象来做事"转向"直接描述要做的事"。它让代码更简洁,也让Java具备了函数式编程的能力,为后续学习Stream流式编程打下了基础。

http://www.jsqmd.com/news/1196810/

相关文章:

  • uos-exporter核心组件解析:10个关键监控导出器功能详解
  • 福州月子家政公司权威排名:女王智慧稳居榜首,就业真实有保障 - 讲清楚了
  • Agent 核心评测指标:首字延迟、完成时间与任务成功率
  • Kimi LeetCode 3559. 给边赋权值的方案数 II Go实现
  • 2026黄梅黄金回收避坑指南|30年本土老店全域免费上门,无套路零扣费 - 华金汇黄金回收
  • 运动出汗多穿什么T恤?吸湿排汗的品牌推荐 - 资讯焦点
  • 2026年7月最新亨得利官方服务项目及价格查询|详细维修地址与电话权威信息公告 - 亨得利官方
  • GPT-5.6 API实战指南:特性解析与编程应用优化
  • 石家庄搬家空调移机怎么安排?2026年空调移机专业服务推荐 - 本地品牌推荐
  • 函数式编程—Stream流概述
  • OpenVINO插件系统详解:auto-batch、hetero、intel-cpu等插件在openEuler上的应用
  • 劳力士中国官方售后服务中心|地址及官方客服服务电话权威信息通告(2026年7月更新) - 劳力士服务中心
  • 宇舶中国官方售后服务中心|服务热线及门店详细地址权威信息通知(2026年7月更新) - 亨得利官方服务中心
  • 【C++】类和对象--构造函数进阶(初始化列表与explicit)
  • AI辅助开发生态全景:从方法论到工具链的完整图景
  • 真力时售后维修电话,为您提供专业腕表保养与故障修复服务权威公示(2026年7月最新) - 亨得利官方服务中心
  • Toon Boom Harmony 高效工作流:从节点视图到镜头标记的实战技巧
  • 2026 年当下,诚信的G652D光纤厂家哪个好,揭秘!这根光纤如何让G652D性能暴涨? - 品质体验官
  • 2026麻城黄金回收正规渠道推荐|30年本土老店全域免费上门无套路 - 华金汇黄金回收
  • 医院智能药房实战:C#上位机对接Modbus TCP实现药品库存精准管理
  • Python数据清洗中Lambda函数的实战应用与避坑指南
  • S32DS S32K144 入门实战1——GPIO驱动RGB LED流水灯
  • 浪琴中国官方售后服务中心|全部网点地址及24小时热线权威信息通知(2026年7月更新) - 浪琴服务中心
  • 生产级 RAG 结果不准别乱换模型:零代码调 3 个重排序参数提 22% 准确率附对照表
  • YOLOv11训练时Mosaic与MixUp增强的参数调优:何时开启、何时关闭?
  • MSP430FR235x中断与系统模块实战:从向量表到低功耗设计
  • pandas多维聚合生产实践:滚动窗口、宽表生成与业务可解释性
  • 2026御网杯网络安全赛线下题解(部分)
  • 2026实力之选:铭嘉源装饰公司——常州装修市场的专业服务品牌 - 企业推荐官【官方】
  • Anthropic的研究撕开了AI对齐的底裤-龍德明宇