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

JDK 8 新增特性:Lambda 表达式

一、

什么是 Lambda 表达式?

        Lambda 表达式是 JDK 8 引入的一种新的语法特性,它允许我们将函数作为参数传递给方法,或者将代码视为数据。Lambda 表达式的基本形式是:

(parameters) -> expression//或者(parameters) -> { statements; }

为什么要用Lambda 表达式

  1. 简化代码:Lambda 表达式可以替代匿名内部类,使代码更加简洁。
  2. 函数式编程:Lambda 表达式支持函数式编程,使得 Java 可以更好地处理集合数据。
  3. 提高可读性:通过 Lambda 表达式,代码的可读性得到了显著提升。

 示例:

        假设我们有一个 Person 类,包含 name 和 age 两个属性。我们希望对一个 Person 列表进行排序,并打印出排序后的结果。

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;class Person {String name;int age;Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return name + " (" + age + ")";}
}public class LambdaExample {public static void main(String[] args) {List<Person> people = Arrays.asList(new Person("Alice", 30),new Person("Bob", 25),new Person("Charlie", 35));// 使用 Lambda 表达式进行排序Collections.sort(people, (p1, p2) -> p1.name.compareTo(p2.name));// 打印排序后的结果people.forEach(System.out::println);}
}

        在这个例子中,我们使用 Lambda 表达式 

(p1, p2) -> p1.name.compareTo(p2.name) 作为 Comparator 传递给 Collections.sort 方法,实现了对 Person 列表按名字排序的功能。

二、

使用 Lambda 表达式的前提条件:

        Lambda 表达式只能用于函数式接口(Functional Interface),即只有一个抽象方法的接口。常见的函数式接口包括 RunnableComparatorPredicate 等。

 

Lambda 表达式的书写规则:

  1. 参数列表:如果只有一个参数,可以省略括号 ()。如果没有参数,必须使用空括号 ()
  2. 箭头:使用 -> 将参数列表与 Lambda 体分隔开。
  3. Lambda 体:如果 Lambda 体只有一条语句,可以省略大括号 {} 和 return 关键字。如果有多条语句,必须使用大括号 {} 并明确使用 return 关键字。

Lambda 表达式省略书写的规则:

  1. 类型推断:编译器可以根据上下文推断参数类型,因此可以省略参数类型。
  2. 单个参数省略括号:如果只有一个参数,可以省略括号 ()
  3. 单条语句省略大括号:如果 Lambda 体只有一条语句,可以省略大括号 {} 和 return 关键字。 

 

示例代码:

有参数的 Lambda 表达式:
// 正常书写
Comparator<Person> comparator1 = (Person p1, Person p2) -> {return p1.name.compareTo(p2.name);
};// 省略书写
Comparator<Person> comparator2 = (p1, p2) -> p1.name.compareTo(p2.name);
 无参数的 Lambda 表达式:
// 正常书写
Runnable runnable1 = () -> {System.out.println("Hello, Lambda!");
};// 省略书写
Runnable runnable2 = () -> System.out.println("Hello, Lambda!");

三、

Lambda 表达式底层实现原理(了解即可)

        Lambda 表达式的底层实现依赖于 Java 的 invokedynamic 指令和 MethodHandle 机制。编译器会将 Lambda 表达式转换为一个私有的静态方法,并通过 invokedynamic 指令在运行时动态绑定该方法。

解释:

  1. invokedynamic 指令:这是 Java 7 引入的一种新的字节码指令,用于支持动态语言的运行时绑定。Lambda 表达式利用这个指令在运行时动态绑定方法。
  2. MethodHandle:这是一个类似于反射的机制,但它更加高效和灵活。Lambda 表达式在底层会使用 MethodHandle 来调用生成的静态方法。

        Lambda 表达式在编译时会被转换为一个静态方法,并在运行时通过 invokedynamic 指令动态绑定这个方法,从而实现高效的函数式编程。

四、

Lambda 表达式与匿名内部类的区别

底层实现原理的区别:
  • 匿名内部类:编译器会为每个匿名内部类生成一个新的类文件,并在运行时加载这些类文件。这会导致额外的类加载开销和内存占用。
  • Lambda 表达式:编译器会将 Lambda 表达式转换为一个私有的静态方法,并通过 invokedynamic 指令在运行时动态绑定该方法,避免了生成额外的类文件,从而提高了性能。
书写区别:
  • 匿名内部类:需要显式地实现接口或继承类,代码较为冗长。
  • Lambda 表达式:代码简洁,省略了接口名称和方法名称。
使用条件的区别:
  • 匿名内部类可以用于任何接口或类,不限于函数式接口。
  • Lambda 表达式只能用于函数式接口,即只有一个抽象方法的接口
示例1: 
// 使用匿名内部类实现 Runnable 接口
Runnable runnable1 = new Runnable() {@Overridepublic void run() {System.out.println("Hello, Anonymous Inner Class!");}
};
runnable1.run();// 使用 Lambda 表达式实现 Runnable 接口
Runnable runnable2 = () -> System.out.println("Hello, Lambda!");
runnable2.run();
示例2:

        假设我们有一个 Calculator 接口,包含一个 int calculate(int a, int b) 方法。我们可以使用匿名内部类和 Lambda 表达式分别实现这个接口。

interface Calculator {int calculate(int a, int b);
}public class LambdaVsAnonymous {public static void main(String[] args) {// 使用匿名内部类实现 Calculator 接口Calculator calculator1 = new Calculator() {@Overridepublic int calculate(int a, int b) {return a + b;}};System.out.println("Anonymous Inner Class: " + calculator1.calculate(10, 20));// 使用 Lambda 表达式实现 Calculator 接口Calculator calculator2 = (a, b) -> a + b;System.out.println("Lambda Expression: " + calculator2.calculate(10, 20));}
}

总结:       

        看到这里我相信你肯定能感受到,Lambda 表达式在代码简洁性和可读性方面具有明显优势。

掌握jdk8的一些新增特性,对我们是很加分的也能提升技术,提高编程效率,希望对你有帮助。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 亚信安全出席第五届国际反病毒大会 探究AI现代网络勒索治理
  • 骨传导耳机哪个品牌好用?精选五大高能骨传导耳机分享!
  • Learn OpenGL In Qt之着色器
  • 深度学习算法:现代人工智能的核心驱动
  • STL集合
  • 如何远程实时监控员工的电脑屏幕?远程桌面监控的五个可实现方法分享
  • soup.find(‘div‘)获取的数据长度为3,为什么1和3都是空的?
  • 研1日记8
  • ZAB协议(算法)
  • SpringBoot框架:大学生租房市场的技术突破
  • Qt TabWidget添加多个窗口,实现分页窗体布局
  • github源码指引:共享内存、数据结构与算法:树形结构ListTree
  • 菜单权限功能设计
  • 算法_队列+宽度优先搜索---持续更新
  • 数据库C语言删除修改和输出
  • ----------
  • [iOS]Core Data浅析一 -- 启用Core Data
  • 【347天】每日项目总结系列085(2018.01.18)
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • dva中组件的懒加载
  • es6要点
  • Java 多线程编程之:notify 和 wait 用法
  • java8-模拟hadoop
  • JavaScript 基本功--面试宝典
  • Java比较器对数组,集合排序
  • java取消线程实例
  • js写一个简单的选项卡
  • Laravel 中的一个后期静态绑定
  • leetcode-27. Remove Element
  • Python实现BT种子转化为磁力链接【实战】
  • React-生命周期杂记
  • Redis在Web项目中的应用与实践
  • 从0到1:PostCSS 插件开发最佳实践
  • 前端每日实战 2018 年 7 月份项目汇总(共 29 个项目)
  • 浅析微信支付:申请退款、退款回调接口、查询退款
  • 无服务器化是企业 IT 架构的未来吗?
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • 移动端 h5开发相关内容总结(三)
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • ​补​充​经​纬​恒​润​一​面​
  • (4)STL算法之比较
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (超详细)2-YOLOV5改进-添加SimAM注意力机制
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (二)hibernate配置管理
  • (附源码)springboot车辆管理系统 毕业设计 031034
  • (附源码)ssm码农论坛 毕业设计 231126
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (每日持续更新)jdk api之FileFilter基础、应用、实战
  • (四)事件系统
  • (转)Linux下编译安装log4cxx
  • *p=a是把a的值赋给p,p=a是把a的地址赋给p。
  • .bat批处理出现中文乱码的情况
  • .net core使用ef 6