如何理解 Java 8 引入的 Lambda 表达式及其使用场景
Lambda表达式是Java 8引入的一项重要特性,它使得编写简洁、可读和高效的代码成为可能。Lambda表达式本质上是一种匿名函数,能够更简洁地表示可传递的代码块,用于简化函数式编程的实现。
一、Lambda表达式概述
1. 什么是Lambda表达式
Lambda表达式是一种匿名函数,表示一段可传递的代码块,能够接受参数并返回结果。它是一种函数式接口(Functional Interface)的实例。函数式接口是仅包含一个抽象方法的接口,例如Runnable、Callable、Comparator等。
Lambda表达式的引入旨在简化匿名内部类的使用,特别是在集合和流操作中,使代码更加简洁和易读。
2. Lambda表达式的语法
Lambda表达式的基本语法如下:
(parameters) -> expression
或
(parameters) -> { statements; }
具体语法形式包括:
- 无参数:
() -> System.out.println("Hello, World!"); - 一个参数,无需括号:
x -> x * x - 多个参数:
(x, y) -> x + y - 带有参数类型:
(int x, int y) -> x + y - 多行语句:
(x, y) -> { int sum = x + y; return sum; }
3. Lambda表达式的类型推断
Java编译器能够根据上下文推断Lambda表达式的参数类型,因此在大多数情况下,可以省略参数类型。例如:
Comparator<String> comparator = (a, b) -> a.compareToIgnoreCase(b);
在上面的例子中,编译器知道Comparator的类型参数是String,因此可以推断出a和b都是String类型。
二、使用Lambda表达式的场景
1. 替代匿名内部类
Lambda表达式最常见的用途之一是替代匿名内部类,使代码更加简洁。例如,在事件处理和线程创建中,可以使用Lambda表达式代替匿名内部类。
事件处理
Java 8之前的代码:
button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("Button clicked!");}
});
使用Lambda表达式:
button.addActionListener(e -> System.out.println("Button clicked!"));
线程创建
Java 8之前的代码:
new Thread(new Runnable() {@Overridepublic void run() {System.out.println("Thread running");}
}).start();
使用Lambda表达式:
new Thread(() -> System.out.println("Thread running")).start();
2. 集合操作
Lambda表达式在集合操作中极为有用,特别是结合Java 8引入的Stream API,可以极大地简化代码并提高可读性。
过滤和映射
Java 8之前的代码:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
List<String> filtered = new ArrayList<>();
for (String s : strings) {if (!s.isEmpty()) {filtered.add(s);}
}
使用Lambda表达式和Stream API:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
List<String> filtered = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
排序
Java 8之前的代码:
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
Collections.sort(names, new Comparator<String>() {@Overridepublic int compare(String a, String b) {return a.compareTo(b);}
});
使用Lambda表达式:
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
names.sort((a, b) -> a.compareTo(b));
3. 自定义函数式接口
除了使用已有的函数式接口,我们还可以自定义函数式接口,并使用Lambda表达式进行实现。
定义函数式接口
@FunctionalInterface
interface MyFunctionalInterface {void execute();
}
使用Lambda表达式实现接口
MyFunctionalInterface myFunction = () -> System.out.println("Executing...");
myFunction.execute();
三、Java 8中的其他相关特性
1. 内置函数式接口
Java 8引入了一些常用的函数式接口,位于java.util.function包中,包括:
Predicate<T>:接受一个参数,返回boolean。常用于条件判断。Function<T, R>:接受一个参数,返回一个结果。常用于转换操作。Consumer<T>:接受一个参数,无返回值。常用于执行操作。Supplier<T>:无参数,返回一个结果。常用于提供对象。BinaryOperator<T>:接受两个参数,返回一个结果。常用于二元运算。
示例
// Predicate
Predicate<String> isNotEmpty = s -> !s.isEmpty();
List<String> nonEmptyStrings = strings.stream().filter(isNotEmpty).collect(Collectors.toList());// Function
Function<String, Integer> toLength = String::length;
List<Integer> lengths = strings.stream().map(toLength).collect(Collectors.toList());// Consumer
Consumer<String> print = System.out::println;
strings.forEach(print);// Supplier
Supplier<String> stringSupplier = () -> "Hello";
String s = stringSupplier.get();// BinaryOperator
BinaryOperator<Integer> sum = Integer::sum;
int result = sum.apply(1, 2);
2. 方法引用
方法引用是一种更简洁的Lambda表达式写法,用于直接引用已有的方法。方法引用的语法有四种形式:
- 静态方法引用:
ClassName::staticMethod - 实例方法引用:
instance::instanceMethod - 特定类型的任意对象的方法引用:
ClassName::instanceMethod - 构造器引用:
ClassName::new
示例
// 静态方法引用
Function<String, Integer> parseInt = Integer::parseInt;// 实例方法引用
String str = "Hello";
Supplier<String> stringSupplier = str::toUpperCase;// 特定类型的任意对象的方法引用
Function<String, String> toUpperCase = String::toUpperCase;// 构造器引用
Supplier<List<String>> listSupplier = ArrayList::new;
四、Lambda表达式的优势和局限
1. 优势
- 简洁性:Lambda表达式大大简化了代码,使代码更加简洁和易读。
- 函数式编程:Lambda表达式支持函数式编程,使得Java能够更好地处理集合操作和并行流处理。
- 代码重用:通过使用Lambda表达式和方法引用,可以更容易地实现代码重用。
2. 局限
- 调试困难:由于Lambda表达式是匿名的,调试和排查问题可能比传统方法更困难。
- 学习曲线:对于没有函数式编程背景的开发者,理解和使用Lambda表达式可能需要一些时间。
- 性能开销:虽然Lambda表达式的性能一般较好,但在某些情况下,可能会引入额外的开销,如创建大量短命对象。
五、实战示例
以下是一个完整的示例,展示如何使用Lambda表达式和Stream API处理集合数据。
示例背景
假设我们有一个员工列表,我们需要进行以下操作:
- 过滤出年龄大于30的员工。
- 提取员工的名字。
- 对名字进行排序。
- 将名字转换为大写。
- 打印结果。
代码实现
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;class Employee {private String name;private int age;public Employee(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public int getAge() {return age;}@Overridepublic String toString() {return "Employee{name='" + name + "', age=" + age + '}';}
}public class LambdaExample {public static void main(String[] args) {List<Employee> employees = Arrays.asList(new Employee("John", 25),new Employee("Jane", 35),new Employee("Jack", 40),new Employee("Jill", 22));List<String> result = employees.stream().filter(e -> e.getAge() > 30).map(Employee::getName).sorted().map(String::toUpperCase).collect(Collectors.toList());result.forEach(System.out::println);}
}
输出结果
JACK
JANE
通过这个示例,我们可以看到Lambda表达式和Stream API如何简化集合数据的处理,并使代码更加简洁和易读。
Lambda表达式是Java 8引入的一个重要特性,极大地增强了Java的表达能力和简洁性。通过Lambda表达式,开发者可以更方便地编写函数式代码,简化集合操作,提升代码的可读性和可维护性。
结合Stream API和方法引用,Lambda表达式使得Java能够更好地应对现代编程需求。尽管Lambda表达式也有其局限性,但它在提升开发效率和代码质量方面的优势是显而易见的。掌握和熟练运用Lambda表达式,对于现代Java开发者来说是必不可少的技能。
黑马程序员免费预约咨询

相关文章:
如何理解 Java 8 引入的 Lambda 表达式及其使用场景
Lambda表达式是Java 8引入的一项重要特性,它使得编写简洁、可读和高效的代码成为可能。Lambda表达式本质上是一种匿名函数,能够更简洁地表示可传递的代码块,用于简化函数式编程的实现。 一、Lambda表达式概述 1. 什么是Lambda表达式 Lambd…...
GPT-4与GPT-4O的区别详解:面向小白用户
1. 模型介绍 在人工智能的语言模型领域,OpenAI的GPT-4和GPT-4O是最新的成员。这两个模型虽然来源于相同的基础技术,但在功能和应用上有着明显的区别。 GPT-4:这是一个通用型语言模型,可以理解和生成自然语言。无论是写作、对话还…...
使用throttle防止按钮多次点击
背景:如上图所示,点击按钮,防止按钮点击多次 <div class"footer"><el-button type"primary" click"submitThrottle">发起咨询 </el-button> </div>import { throttle } from loda…...
Echarts 在折线图的指定位置绘制一个图标展示
文章目录 需求分析需求 在线段交汇处用一个六边形图标展示 分析 可以使用 markPoint 和 symbol 属性来实现。这是一个更简单和更标准的方法来添加标记点在运行下述代码后,你将在浏览器中看到一个折线图,其中在 [3, 35] (即图表中第四个数据点 Thu 的 y 值为 35 的位置)处…...
适用于 Windows 的 8 大数据恢复软件
数据恢复软件可帮助您恢复因意外删除或由于某些技术故障(如硬盘损坏等)而丢失的数据。这些工具可帮助您从硬盘驱动器 (HDD) 中高效地恢复丢失的数据,因为这些工具不支持从 SSD 恢复数据。重要的是要了解,您删除的数据不会被系统永…...
HTTP基础
一、HTTP协议 1、HTTP协议概念 HTTP的全称是:Hyper Text Transfer Protocol,意为 超文本传输协议。它指的是服务器和客户端之间交互必须遵循的一问一答的规则。形容这个规则:问答机制、握手机制。 它规范了请求和响应内容的类型和格式, 是基于…...
深入了解Linux命令:visudo
深入了解Linux命令:visudo 在Linux系统中,sudo(superuser do)是一个允许用户以其他用户身份(通常是超级用户或其他用户)执行命令的程序。sudo的配置文件/etc/sudoers存储了哪些用户可以执行哪些命令的权限…...
十大排序 —— 希尔排序
十大排序 —— 希尔排序 什么是希尔排序插入排序希尔排序递归版本 我们今天来看另一个很有名的排序——希尔排序 什么是希尔排序 希尔排序(Shell Sort)是插入排序的一种更高效的改进版本,由Donald Shell于1959年提出。它通过比较相距一定间…...
SpringCloud Hystrix服务熔断实例总结
SpringCloud Hystrix断路器-服务熔断与降级和HystrixDashboard SpringCloud Hystrix服务降级实例总结 本文采用版本为Hoxton.SR1系列,SpringBoot为2.2.2.RELEASE <dependency><groupId>org.springframework.cloud</groupId><artifactId>s…...
为什么没有输出九九乘法表?
下面的程序本来想输出九九乘法表到屏幕上,为什么没有输出呢?怎样修改? <!DOCTYPE html> <html> <head> <meta charset"utf-8" /> <title>我的HTML练习</title> …...
EasyRecovery5步轻松恢复电脑手机数据,EasyRecovery带你探索!
在当今的数字化时代,数据已经成为我们生活和工作中不可或缺的一部分。无论是个人照片、工作文件还是重要的商业信息,数据的安全存储和恢复都显得尤为重要。EasyRecovery作为一款广受欢迎的数据恢复软件,为用户提供了强大的数据恢复功能&#…...
904. 水果成篮
904. 水果成篮 原题链接:完成情况:解题思路:参考代码:_904水果成篮_滑动窗口 错误经验吸取 原题链接: 904. 水果成篮 https://leetcode.cn/problems/fruit-into-baskets/description/ 完成情况: 解题思…...
在618集中上新,蕉下、VVC们为何押注拼多多?
编辑|Ray 自前两年崛起的防晒产品,今年依旧热度不减。 头部品牌蕉下,2020年入驻拼多多,如今年销售额已过亿元。而自去年起重点押注拼多多的时尚防晒品牌VVC,很快销量翻番。这两家公司,不约而同在618之前上…...
Maximo Attachments配置
以下内容以 Windows 上 Maximo 为例,并假定设置 DOCLINKS 的根路径为 “C:\DOCLINKS”。 HTTP Server配置 修改C:\Program Files\IBM\HTTPServer\conf\httpd.conf文件 查找 “DocumentRoot” 并修改成如下配置 DocumentRoot "C:\DOCLINKS"查找 “<…...
一分钟了解香港的场外期权报价
香港的场外期权报价 在香港这个国际金融中心,场外期权交易是金融市场不可或缺的一部分。场外期权,作为一种非标准化的金融衍生品,为投资者提供了在特定时间以约定价格买入或卖出某种资产的机会。对于希望参与这一市场的投资者来说࿰…...
专业开放式耳机什么牌子更好?六大技巧教你不踩坑!
相信很多入坑的朋友再最开始挑选耳机的时候都会矛盾,现在市面上这么多耳机,我该怎么选择?其实对于开放式耳机,大家都没有一个明确的概念,可能会为了音质的一小点提升而耗费大量的资金,毕竟这是一个无底洞。…...
注意!!24软考系统集成有变化,第三版考试一定要看这个!
系统集成在今年年初改版之后,上半年的考试也取消了,留给大家充足的时间来学习新的教材和考纲。但11月也将是第三版考纲的第1次考试,重点到底有什么?今天带大家详细的了解一下最新版中项考试大纲。 一、考试说明 1.考试目标 通过…...
Redis数据结构HyperLogLog以及布隆过滤器
HyperLogLog 引言 在开始之前,先思考一个常见的业务问题:如果负责开发维护一个大型的网站,有一天老板找产品经理要网站每个网页每天的UV数据,然后来开发这个统计模块,需要如何实现? 如果统计PV非常好办&…...
C++——从C语言快速入门
目录 一、数组 1、声明数组 2、初始化数组 3、访问数组元素 4、示例 5、注意事项 6、数组小练习 计算器支持加减乘除 数组找最大值 二、指针 三、字符串 string 类型 一、数组 在 C 中,数组是一种存储固定大小的相同类型元素的序列。数组的所有元素都存…...
thinkpad T440p ubuntu-slam软件安装记录
安装问题 1.ubuntu20.04安装后提示"x86/cpu:VMX(outside TXT) disabled by BIOS" 这是虚拟化被禁止了,到BIOS里去把Virtualization选项打开即可。 2.ACPI Error:Needed type[Reference],found [Integer] 等错误 link这篇博客中提到该问题,…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...
