首页 > 其他分享 >Lambda 表达式

Lambda 表达式

时间:2023-01-25 20:00:52浏览次数:45  
标签:代码 匿名 实例 public 表达式 Lambda


Lambda 表达式是一个 Java 8 以后开始支持的一个非常优雅的新特性,本小节我们将学习什么是 Lambda 表达式,为什么需要 Lambda 表达式,Lambda 表达式的基础语法,以及 Lambda 表达式的实际应用等内容。

1. 什么是 Lambda 表达式

Lambda 表达式基于数学中的​​ λ 演算​​得名,直接对应于其中的 lambda 抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。

Lambda 表达式是一个匿名函数,匿名函数由 ​​LISP​​ 语言在 1958 年首先采用,此后,越来越多的编程语言开始陆续采用。

我们可以把 Lambda 表达式理解为是一段可传递的代码(将代码像数据一样传递)。使用它可以写出简洁、灵活的代码。作为一种更紧凑的代码风格,使 Java 语言的表达能力得到了提升。

2. 为什么需要 Lambda 表达式

在 Java 8 之前,编写一个匿名内部类的代码很冗长、可读性很差,请查看如下实例:

public class LambdaDemo1 {

public static void main(String[] args) {

// 实例化一个 Runnable 接口的匿名实现类对象
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Hello, 匿名内部类");
}
};
// 执行匿名内部类的 run() 方法
runnable.run();
}

}

运行结果:

Hello, 匿名内部类

Lambda 表达式的应用则使代码变得更加紧凑,可读性增强;另外,Lambda 表达式使并行操作大集合变得很方便,可以充分发挥多核 CPU 的优势,更易于为多核处理器编写代码。

下面我们使用 ​​Lambda​​ 表达式改写上面的代码。

如果你使用 ​​IDEA​​​ 编写代码,可以直接一键智能修改,首先,将鼠标光标移动到灰色的 ​​new Runnable()​​​ 代码处,此时会弹出一个提示框,提示可以使用 ​​Lambda​​​ 表达式替换,点击 ​​Replace with lambda​​ 按钮即可完成代码替换,截图如下:

修改后实例如下:

public class LambdaDemo1 {

public static void main(String[] args) {

// 实例化一个 Runnable 接口的匿名实现类对象
Runnable runnable = () -> System.out.println("Hello, 匿名内部类");
// 执行匿名内部类的 run() 方法
runnable.run();
}

}

运行结果:

Hello, 匿名内部类

通过对比,使用 ​​lambda​​ 表达式实现了与匿名内部类同样的功能,并且仅仅用了一行代码,代码变得更加简洁了。对于这样的写法,你可能还非常疑惑,但别担心,我们马上就来详细讲解基础语法。

3. 基础语法

Lambda 表达式由三个部分组成:

  • 一个括号内用逗号分隔的形式参数列表:实际上就是接口里面抽象方法的参数;
  • 一个箭头符号:->,这个箭头我们又称为 Lambda 操作符或箭头操作符;
  • 方法体:可以是表达式和代码块,是重写的方法的方法体。语法如下:
  1. 方法体为表达式,该表达式的值作为返回值返回。
(parameters) -> expression
  1. 方法体为代码块,必须用 {} 来包裹起来,且需要一个 return 返回值,但若函数式接口里面方法返回值是 void,则无需返回值。
(parameters) -> {
statement1;
statement2;
}

4. 使用实例

通过上面一系列内容的学习,我们可以得出一个结论:Lambda 表达式本质上就是接口实现类的对象,它简化了之前匿名内部类的冗长代码的编写。

关于 Lambda 表达式的具体使用,我们将根据语法格式分为 5 种展开介绍。

4.1 无参数无返回值

无参数无返回值,指的是接口实现类重写的方法是无参数无返回值的,我们一开始提到的 ​​Runnable​​ 接口匿名内部类就属于此类:

public class LambdaDemo2 {

public static void main(String[] args) {
// 通过匿名内部类实例实例化一个 Runnable 接口的实现类
Runnable runnable1 = new Runnable() {
@Override
public void run() { // 方法无形参列表,也无返回值
System.out.println("Hello, 匿名内部类");
}
};
// 执行匿名内部类的 run() 方法
runnable1.run();

// 无参数无返回值,通过 lambda 表达式来实例化 Runnable 接口的实现类
Runnable runnable2 = () -> System.out.println("Hello, Lambda");
// 执行通过 lambda 表达式实例化的对象下的 run() 方法
runnable2.run();
}

}

运行结果:

Hello, 匿名内部类
Hello, Lambda

4.2 单参数无返回值

无参数无返回值,指的是接口实现类重写的方法是单个参数,返回值为 ​​void​​ 的,实例如下:

import java.util.function.Consumer;

public class LambdaDemo3 {

public static void main(String[] args) {

// 单参数无返回值
Consumer<String> consumer1 = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer1.accept("Hello World!");

Consumer<String> consumer2 = (String s) -> {
System.out.println(s);
};
consumer2.accept("你好,世界!");
}

}

运行结果:

Hello World!
你好,世界!

4.3 省略数据类型

什么叫省略数据类型呢?我们依旧采用上面的实例,使用 ​​Lambda​​ 表达式可以省略掉括号中的类型,实例代码如下:

// 省略类型前代码
Consumer<String> consumer2 = (String s) -> {
System.out.println(s);
};
consumer2.accept("你好,世界!");

// 省略类型后代码
Consumer<String> consumer3 = (s) -> {
System.out.println(s);
};
consumer3.accept("你好,世界!");

Tips:之所以能够省略括号中的数据类型,是因为我们在 ​​Comsumer<String>​​ 处已经指定了泛型,编译器可以推断出类型,后面就不用指定具体类型了。称为类型推断

4.4 省略参数的小括号

当我们写的 ​​Lambda​​ 表达式只需要一个参数时,参数的小括号就可以省略,改写上面实例的代码:

// 省略小括号前代码
Consumer<String> consumer3 = (s) -> {
System.out.println(s);
};
consumer3.accept("你好,世界!");
// 省略小括号后代码
Consumer<String> consumer4 = s -> {
System.out.println(s);
};
consumer3.accept("你好,世界!");

观察实例代码,之前的 ​​(s) ->​​​ 可以改写成 ​​s ->​​,这样写也是合法的。

4.5 省略 return 和大括号

当 ​​Lambda​​ 表达式体只有一条语句时,如果有返回,则 return 和大括号都可以省略,实例代码如下:

import java.util.Comparator;

public class LambdaDemo4 {

public static void main(String[] args) {

// 省略 return 和 {} 前代码
Comparator<Integer> comparator1 = (o1, o2) -> {
return o1.compareTo(o2);
};
System.out.println(comparator1.compare(12, 12));

// 省略 return 和 {} 后代码
Comparator<Integer> comparator2 = (o1, o2) -> o1.compareTo(o2);
System.out.println(comparator2.compare(12, 23));

}
}

运行结果:

0
-1

5. 小结

通过本小节的学习,我们知道了 ​​Lambda​​​ 表达式并不是 Java 所特有的特性,很多主流编程语言都支持 ​​Lambda​​ 表达式,在 Java 中,Lambda 表达式实际上就是接口实现类的对象,它简化了之前匿名内部类的冗长代码的编写。Lambda 表达式能使代码变得更加紧凑,增强代码的可读性;另外,Lambda 表达式使并行操作大集合变得很方便,可以充分发挥多核 CPU 的优势,更易于为多核处理器编写代码。

我们也通过大量的实例代码介绍了 ​​Lambda​​​ 的语法格式和实际使用,通过这些实例,可以发现 ​​Lambda​​​ 表达式对于接口也是有要求的 —— 接口内部只能包含一个抽象方法,如果接口内部包含多个抽象方法,我们就无法使用 ​​Lambda​​ 表达式了,这样只包含一个抽象方法的接口,我们称为函数式接口,下一小节我们将详细介绍函数式接口。

标签:代码,匿名,实例,public,表达式,Lambda
From: https://blog.51cto.com/10zhancom/6022788

相关文章

  • 代码随想录算法训练营day11 | leetcode 20. 有效的括号 1047. 删除字符串中的所有相邻
    基础知识StringStringBuilder操作publicclassStringOperation{intstartIndex;intendIndex;{//初始容量为16个字符主要做增删查......
  • Web APIs 正则表达式
    一、正则表达式1.1什么是正则表达式正则表达式(RegularExpression)是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象通常用来查找、替换那些符合......
  • Python入门之真值表达式
    """真值表达式if数据:语句本质就是使用bool函数操作数据条件表达式"""#1.真值表达式if"a":#ifbool("a"):print("真......
  • 08_字符串扩展_3.3_表达式的格式化
    """_*_coding:utf-8_*_@Time:2023/1/2221:19@Author:软柠柠吖@Description:表达式的格式化表达式:一条具有明确执行结果的代码语句使用场......
  • 正则表达式
    先附上链接sheepcode在C++中的用法为什么使用双反斜杠:因为d表示d这个字符,\d表示所有数字,而要表示\d,就要表示\,所以要用一个反斜杠来转义\,于是形成\d例题Leecode.65c......
  • 游戏程序报错:表达式必须是可修改的左值
    提问: C++编程:表达式必须是可修改的左值报错:①表达式必须是可修改的左值"weaponType":不能给常量赋值②表达式必须是可修改的左值“=”:左操作数必须为左值如图一:  ......
  • C# lambda+委托
    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespacelearn_lambda2{internalcla......
  • LINUX学习之正则表达式(十二)
    普通正则元字符元字符匹配描述.匹配除了换行符以外的任意单个字符*前导字符出现0次或连续多次.*任意长度字符^行首(以…开头)$行尾(以…结尾)......
  • 跟我20天学Java:02-自动类型转换,表达式的自动类型转换,强制类型转换
    文章目录​​学习目标​​​​一、什么是自动类型转换,为什么要学习自动类型转换?​​​​总结​​​​二、表达式的自动类型转换​​​​总结​​​​三、强制转化类型​​​......
  • Spring AOP中@Pointcut切入点表达式详解
    目录一、瞅一眼标准的AspectJAop的pointcut的表达式二、SpringAop的十一种AOP表达式三、演示使用1、execution:2、within:3、this:4、target:5、args:6、@target:7、......