【Java8新特性】- Lambda表达式

1|0Java8新特性 - Lambda表达式

😄生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆 一个有梦有戏的人 @怒放吧德德
🌝分享学习心得,欢迎指正,大家一起学习成长!

lambda表达式.jpg

1|1简介

Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。这是来自百度百科对lambda的介绍,实际上lambda就是简化了匿名函数的编写,只需一行代码就能代替繁杂的代码。
lambda主要是可以非常简洁的形式调用我们的匿名函数接口。

1|2简单例子

首先声明一个接口,并且编写实现类实现这个接口

// UserService public interface UserService { void add(); } // UserServiceImpl public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("UserServiceImpl --- add"); } }

一般来说是通过new实现类从而拿到实现中的add方法,如果通过new接口类就需要使用匿名内部类的形式调用接口。IDEA会提示使用lambda表达式。
image.png

如下代码可以看一下对比。

public static void main(String[] args) { UserService userService = new UserServiceImpl(); userService.add(); UserService user = new UserService() { @Override public void add() { // 匿名内部接口业务逻辑 System.out.println("匿名内部接口业务逻辑"); } }; // Lamdba表达式 UserService user2 = () -> System.out.println("匿名内部接口业务逻辑"); user2.add(); }

1|3Lambda表达式的规范

Java中的Lambda表达式的规范,必须是为函数接口。

1|0使用函数式接口

使用Lambda表达式依赖于函数式接口:
1、使用@FunctionalInterface注解来声明函数接口
2、在这个函数接口中只能有一个抽象方法
3、在函数接口中可以定义object类中的方法
4、可以有静态方法
*函数式接口(Functional Interface) 就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
更多函数式接口可以查看菜鸟联盟https://www.runoob.com/java/java8-functional-interfaces.html

1|0函数式接口的定义

通过@FunctionalInterface注解声明接口类,在java中也有许多内置的函数接口,详情看菜鸟联盟。

@FunctionalInterface // 声明函数式接口 public interface UserService { void add(); String toString(); // Object类中的方法 static void hello() { // 静态方法 System.out.println("hello"); } }

1|4Lambda表达式的基础语法

1|0表达式格式

(参数) -> {方法体}

1|0格式说明

():存放参数,留空就代表没有参数。函数接口的参数列表,不需要写类型,需要定义参数名称。
->:是新引入的语法格式,代表指向动作。
{}:方法体

1|0无参方法调用

在接口类中声明一个无参的抽象方法,通过lambda表达式来完成调用。()不需要存放参数,最后将会返回一个实现类对象。在通过调用对象的get方法。

// 匿名内部接口业务逻辑 UserService user2 = () -> System.out.println("匿名内部接口业务逻辑"); user2.get();

更加简便的写法

((UserService)() -> System.out.println("匿名内部接口业务逻辑")).get();

1|0含参数方法调用

在MathService定义一个含有参数的抽象方法,原本的方式通过匿名内部接口。可以通过使用lambda表达式更加简便,并且可以省去{},也不需要return。

MathService math = new MathService() { @Override public Integer add(int a, int b) { return a + b; } }; MathService mathService = (a, b) -> a + b; System.out.println(mathService.add(1, 1));

1|5方法引入

1|0规则

方法引入需要遵循规范:方法参数列表、返回类型与函数接口参数列表与返回类型必须
要保持一致。
方法引入的规则:
       静态方法引入: 类名::(静态)方法名称
       对象方法引入: 类名:: 实例方法名称
       实例方法引入:new对象 对象实例::方法引入
       构造函数引入:类名::new
方法引用提供了非常有用的语法,可以直接引用已有的java类或对象的方法或构造器。方法引用其实也离不开Lambda表达式,
与lambda联合使用 ,方法引用可以使语言的构造更加紧凑简洁,减少冗余代码。方法引用提供非常有用的语法,可以直接引用已有的java类或者对象中方法或者构造函数,
方法引用需要配合Lambda表达式语法一起使用减少代码的冗余性问题。
1664976332232.png

1|6实例

1|0构造器引用

通过构造器引用实例化对象,

public static void main(String[] args) { // 使用匿名内部类 CarService carService = new CarService() { @Override public Car getCar() { return null; } }; // 使用引用方法 CarService car = Car::new; car.getCar(); } public class Car { private String name; private String brand; public Car() { } } public interface CarService { Car getCar(); }

1|0静态方法引入

UserService u = UserService::hello; u.get();

在userservice中,有一个抽象get方法和一个静态方法

@FunctionalInterface public interface UserService { void get(); static void hello() { System.out.println("hello"); } }

运行后会输出hello

hello Process finished with exit code 0

1|0对象方法引入

这是一种更为方便的写法, 我记得在mybatis-plus使用自带条件查询的时候会用到这种方式,以下用简单例子来实现。java8中提供了public interface Function<T, R>的类,这个类也是使用@FunctionalInterface注解,可见也是函数式接口。
代码:

// 在car中声明一个方法 public class Car { public String Info() { return "保时捷 - 帕拉梅拉"; } } // 函数式接口 @FunctionalInterface public interface CarInFoService { String getCar(Car car); }

测试采用了三种方式进行比较

public class LambdaTest4 { public static void main(String[] args) { System.out.println("**************匿名内部类**************"); CarInFoService carInFoService = new CarInFoService() { @Override public String getCar(Car car) { return car.Info(); } }; System.out.println(carInFoService.getCar(new Car())); System.out.println("**************lambda**************"); CarInFoService carInFoService2 = (car) -> car.Info(); System.out.println(carInFoService2.getCar(new Car())); System.out.println("**************对象方法引入**************"); CarInFoService carInFoService3 = Car::Info; System.out.println(carInFoService3.getCar(new Car())); // R apply(T t); T apply方法传递的参数类型 : R apply 方法返回的类型 Function<String, Integer> function = String::length; System.out.println(function.apply("lyd_code")); } }

结果
image.png

1|7Lambda表达式遍历

通过foreach循环遍历,forEach实际上需要使用匿名内部类Consumer<? super E>。
image.png
代码如下

public class LambdaTest5 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("lyd"); list.add("tom"); list.add("jack"); list.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.println("name: " + s); } }); System.out.println("lambda表达式"); /** * s:遍历链表所得到的元素字符串 */ list.forEach(s -> System.out.println("name: " + s)); } }

测试结果
image.png

1|8Lambda排序

通过Comparator匿名内部类

public class LambdaTest6 { public static void main(String[] args) { ArrayList<Student> students = new ArrayList<>(); students.add(new Student("lyd", 99)); students.add(new Student("lkj", 55)); students.add(new Student("llm", 67)); students.add(new Student("lss", 87)); // students.sort(new Comparator<Student>() { // @Override // public int compare(Student o1, Student o2) { // return o1.getScore() - o2.getScore(); // } // }); students.sort((o1, o2) -> o1.getScore() - o2.getScore()); students.forEach(student -> System.out.println("name: " + student.getName() + " score: " + student.getScore())); } }

结果
image.png

为了写好博客,包括代码、文字,我是经过斟酌了的,如果有错误,欢迎指正!感谢观看!
👍创作不易,如有错误请指正,感谢观看!记得点赞哦!👍


__EOF__

本文作者怒放吧德德
本文链接https://www.cnblogs.com/lyd-code/p/16756479.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   怒放吧德德  阅读(604)  评论(3编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示