理解 Lambda 表达式

article/2025/10/4 0:47:00

Java8 Stream 相关集合转换

一、初识 Lambda

简化过程:

  1. 常规实现接口。
  2. 静态内部类。
  3. 局部内部类。
  4. 匿名内部类。
  5. lambda 表达式。
  6. lambda 表达式简化。
public class TestMain {static class StaStudent implements Person {@Overridepublic void speak(String language) {System.out.println("静态内部类" + language);}}public static void main(String[] args) {Person p = new GloStudent();p.speak("lan");p = new StaStudent();p.speak("lan");class LocStudent implements Person {@Overridepublic void speak(String language) {System.out.println("局部内部类" + language);}}p = new LocStudent();p.speak("lan");p = new Person() {@Overridepublic void speak(String language) {System.out.println("匿名内部类" + language);}};p.speak("lan");p = (language) -> {System.out.println("lambda 表达式---块代码1" + language);System.out.println("lambda 表达式---块代码2" + language);};p.speak("lan");//接口是函数式接口才能转换为lambda表达式//在只有一行代码的情况下可以将块简化为行//单个参数可以去掉参数类型,括号可选//多个参数可以同时去掉参数类型,必须括号包裹p = (language) -> System.out.println("lambda 表达式---单行代码" + language);p.speak("lan");}
}class GloStudent implements Person {@Overridepublic void speak(String language) {System.out.println("外部类" + language);}
}interface Person {void speak(String language);
}

二、什么是 Lambda

对于 Java 变量,可以给其赋值。

那么如何把“一块代码”赋给 Java 变量呢?如图把右边代码,赋给左边的 Java 变量 aBlockOfCode:

Java8之后可以利用 Lambda 特性做到,如图:

当然,该写法并不简洁。为使该赋值操作更加简洁,可移除一些无用的声明,如下:

如此就成功的把“一块代码”赋给了一个变量。而“这块代码”,或者说“这个被赋给一个变量的函数”,就是一个 Lambda 表达式。但是这里有个问题,就是变量 aBlockOfCode 的类型是什么?

Java8 中所有的 Lambda 的类型都是一个接口。而 Lambda 表达式本身,也就是“那块代码”,需要是该接口的实现。这是理解 Lambda 的关键所在,简言之,Lambda 表达式本身就是一个接口的实现。便于理解,给 aBlockOfCode 加上一个类型:

这种只有一个函数需要被实现的接口类型,为“函数式接口”。为避免后人在该接口中增加接口函数导致其有多个接口方法需要被实现,变成"非函数接口”,可以在上面加上一个声明@FunctionalInterface,如此就无法在里面添加新的接口函数了:

如此就得到了一个完整的 Lambda 表达式声明:

三、Lambda 表达式:最直观的作用就是使得代码变得异常简洁。

对比一下 Lambda 表达式和传统的 Java 对同一个接口的实现:

两种写法本质上是等价的。但是 Java8 的写法更加优雅简洁。并且由于 Lambda 可以直接赋值给一个变量,就可以直接把 Lambda 作为参数传给函数,而传统的 Java 必须有明确的接口实现的定义,初始化才行:

Java7 要求必须定义一个“污染环境”的接口实现 MyInterfaceImpl。有时,该接口实现只用到一次。相较之下 Java8 的 Lambda 就显得干净很多。

四、Lambda 实践

1️⃣Lambda 结合 FunctionalInterface Lib、forEach、stream()、method reference 等新特性可以使代码变的更加简洁。

假设 Person 的定义和 List 的值都给定:

要打印出 guiltyPersons 里面所有 LastName 以“Z”开头的人的 firstName。

原生态 Lambda 写法:定义两个函数式接口,定义一个静态函数,调用静态函数并给参数赋值 Lambda 表达式。

这个代码实际上已经比较简洁了,但是还可以更简洁么?

当然可以。在 Java8 中有一个函数式接口的包java.util.function(Java Platform SE 8),里面定义了大量可能用到的函数式接口。所以,在这里压根都不需要定义 NameChecker 和 Executor 这两个函数式接口,直接用 Java8 函数式接口包里的 Predicate 和 Consumer 就可以——因为这一对的接口定义和 NameChecker/Executor 其实是一样的。

第一步简化 - 利用函数式接口包:

静态函数里面的 for each 其实是非常碍眼的。这里可以利用 Iterable 自带的 forEach() 来替代。forEach() 本身可以接受一个 Consumer 参数。

第二步简化 - 用 Iterable.forEach() 取代 foreach loop:

由于静态函数其实只是对 List 进行了一通操作,这里可以甩掉静态函数,直接使用 stream() 特性来完成。stream() 的几个方法都是接受 Predicate,Consumer 等参数的java.util.stream(Java Platform SE 8)。理解了上面的内容,stream() 就非常好理解了。

第三步简化 - 利用 stream() 替代静态函数:

对比最开始的 Lambda 写法,这里已经非常简洁了。但是,如果要求变成 print 这个人的全部信息,及 p -> System.out.println§; 那么还可以利用 Method reference 来继续简化。所谓 Method reference 就是用已经写好的别的 Object/Class 的method来代替 Lambda expression。格式如下:

第四步简化 - 如果是 println§,则可以利用 Method reference 代替 forEach 中的 Lambda 表达式:

这基本上就是能写的最简洁的版本了。

2️⃣Lambda 配合 Optional 可以使 Java 对于 null 的处理变的异常优雅。

假设有一个 person object,以及一个 person object 的 Optional wrapper:

Optional 如果不结合 Lambda 使用的话,并不能使原来繁琐的 null check 变的简单。

只有当 Optional 结合 Lambda 一起使用的时候,才能发挥出其真正的威力。现在就来对比一下下面四种常见的 null 处理中,Java8 的 Lambda+Optional 和传统 Java 两者之间对于 null 的处理差异。

情况一 - 存在则开干

情况二 - 存在则返回,不存在则自定义返回

情况三 - 存在则返回,无则由函数产生

情况四 - 夺命连环 null 检查

由上述四种情况可以清楚地看到,Optional+Lambda 可以少写很多 if/else。尤其是对于情况四,传统 Java 的写法显得冗长难懂,而新的 Optional+Lambda 则清楚简洁。


http://chatgpt.dhexx.cn/article/9xom2aOp.shtml

相关文章

C++11——lambda表达式

目录 前言 一.lambda表达式用法 二.lambda表达式语法 三.lambda表达式的原理 前言 在显示生活中,我们在用手机购物时。总是可以在页面上看到下面这样的选项。 我们知道底层这是通过排序来完成的,但是当我们实现时,要写多个排序算法&#x…

C++ lambda 表达式深剖

目录 传统艺能😎概念🤔语法🤔捕获方式🤔相互赋值😎 mutable🤔底层原理🤔 传统艺能😎 小编是双非本科大一菜鸟不赘述,欢迎米娜桑来指点江山哦(QQ:…

Lambda表达式的本质

一直想写一篇文章,来总结lambda表达式,但是之前感觉总结的不是特别到位,现在看了几篇文章和视频后,感觉对lambda表达式有了比较深刻的认识,现在进行记录总结如下: lambda表达式又叫做匿名函数,…

Java Lambda 表达式

目录 一、说明二、理解三、演示1.常规方法实现2.静态内部类3.局部内部类4.匿名内部类5.Lambda表达式6.Lambda再简化 一、说明 Lambda表达式是什么 Lambda 表达式也称为闭包,是Java 8 发布的新特性Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中) …

C++ Lambda表达式

在C11和更高版本中,Lambda表达式(通常称为Lambda)是一种在被调用的位置或作为参数传递给函数的位置定义匿名函数对象(闭包)的简便方法。Lambda通常用于封装传递给算法或异步函数的少量代码行。1 Lambda表达式是C11中一…

java Lambda表达式详解

文章目录 一、背景1.1语法1.2函数式接口 二、Lambda的基本使用2.1引子2.2常见的使用方式2.3语法小结 三、变量捕获3.1 匿名内部类3.2 匿名内部类的变量捕获3.3Lambda的变量捕获 四、Lambda在集合当中的使用4.1 Collection接口4.2 list接口4.3 Map接口 总结 提示:以下…

Lambda表达式详解

Lambda表达式 1. 为什么使用lambda表达式2. 入门案例3. lambda表达式组成4. lambda表达式使用4.1 语法格式一4.2 语法格式二4.3 语法格式三4.4 语法格式四4.5 语法格式五4.6 语法格式六 5. 总结 1. 为什么使用lambda表达式 lambda是一个匿名函数,我们可以吧lambda表…

Lambda 表达式

一.什么事Lambda表达式 Lambda 表达式是一种匿名函数,也可称为闭包,简单地说,它是没有声明的方法,也即没有访问修饰符、返回值声明和名字。 它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使 Java 语言…

Lambda表达式超详细总结(简单易懂)

文章目录 1、什么是Lambda表达式2、为什么使用Lambda表达式3、函数式接口(lambda表达式的使用前提)4、推导Lambda表达式5、Lambda表达式语法 1、什么是Lambda表达式 Lambda表达式,也可称为闭包。其本质属于函数式编程的概念,是Ja…

Lambda表达式超详细总结

文章目录 1. 什么是Lambda表达式2. 为什么使用Lambda表达式3. Lambda表达式语法4. 函数式接口4.1 什么是函数式接口4.2 自定义函数式接口4.3 Java内置函数式接口 5. 方法引用6. 构造器引用7. 数组引用8. Lambda表达式的作用域8.1 访问局部变量8.2 访问局部引用,静态…

SQL语句学习之SQL基础的表创建以及添加数据

SQL语句学习之SQL基础的表创建以及添加数据 学习目标1: 一周内掌握SQL基础语句 tip:主要是在牛客网(牛客网)上进行练习,里面有在线编程,可以直接运行,而且有解题的思路,比较清晰,而…

Hive SQL之表与建表

Hive数据模型总览 用户通过数据库访问Hive后,首先选择哪个数据库,然后在库的下面选择的是一张张表,表是管理数据的的最基本的所在,在表中的一行行记录,在现实中就是一条条数据,里面有我们的字段字段类型和它…

SQLite 创建表SQL语句

SQLite 创建表 创表语法 CREATE TABLE [表名称](--主键列不可为空[列1] [类型] PRIMARY KEY NOT NULL,--列可为空[列2] [类型],--列不可为空[列3] [类型] NOT NULL );创表示例 CREATE TABLE User (Id INT PRIMARY KEY NOT NULL,Name Text,Sex INT NOT NULL )在线Sqlite查看器…

SQL创建表为啥不显示

这里新建表 左上角报存 保存完以后点击刷新就会出来刚创建的表格

SQL 创建表的备份

1. SELECT INTO 语句 SELECT INTO 语句从一个表中选取数据,然后把数据插入另一个表中。 SELECT INTO 语句常用于创建表的备份复件或者用于对记录进行存档; SQL SELECT INTO 语法 您可以把所有的列插入新表: SELECT * INTO new_table_name…

SQL Server创建表

我们要怎么在数据库中创建表呢!首先,表在数据库和模式中唯一命名。每个表包含一个或多个列。 每列都有一个相关的数据类型,用于定义它可以存储的数据类型,例如:数字,字符串和日期。 要创建新表,…

SQL Server 创建表

我们在上一节中完成了数据库的创建,在本节,我们要往这个新的数据库中加入点数据,要想将数据添加到数据库,我们就必须在数据库中添加一个表,接下来来看看具体的操作。 我们的数据库是一个任务跟踪数据库,那…

ORACLE SQL 创建表

1.创建表: 1.1表名和列名: 一定要以字母开头 一定在 1-30 个字符之间 只能包含 A–Z, a–z, 0–9, _, $, 和 # 一定不能和用户定义的其他对象重名 一定不能是Oracle 的保留字 一定要有CREATE TABLE权限 而且需要一定的存储空间 还要指定的&…

利用SQL创建表结构

一、创建图书管理系统,其中涉及到的对象有(图书分类,图书,学生,借书记录) 1、列出关系模式 (1) 书本类别(种类编号,种类名称) (2) 学生(学生编号&#xff0…

SQL创建表

要创建新的表,就要使用create table语句。 1、第一,要指定数据库的名称,必须是数据库有的,如果没有指定,那就默认是当前数据库。(如图下所示是没有指定数据库的) 2、第二,指定表的模…