Java 8的变革:函数式编程和Lambda表达式探索
文章目录
- 一、函数接口
- 二、Lambda表达式简介
- 三、Lambda表达式外部参数
- 四、Lambda范例
- 五、Runnable Lambda表达式
一、函数接口
函数接口是一个具有单个抽象方法的接口,接口设计主要是为了支持 Lambda 表达式和方法引用,使得 Java 能更方便地实现函数式编程风格。
特点和用途:
- 单一抽象方法: 函数接口只能有
一个
抽象方法,但可以有多个
默认方法(default)或静态方法(static)。 - Lambda 表达式: 可以使用函数接口创建 Lambda 表达式,从而简洁地表示匿名函数,例如在集合操作、线程处理等场景中。
- 方法引用: 可以通过函数接口的类型来引用一个已存在的方法,使代码更简洁和可读性更高。
Java 8 提供了几个标准的函数接口,接口通常位于
java.util.function
包中。
常见的函数接口:
-
Consumer: 接收一个输入参数并且不返回结果的操作。
Consumer<String> printConsumer = str -> System.out.println(str); printConsumer.accept("Hello World!");
-
Supplier: 不接收参数但是返回结果的提供型接口。
Supplier<Double> randomSupplier = () -> Math.random(); System.out.println(randomSupplier.get());
-
Function: 接收一个输入参数,并返回结果。
Function<Integer, String> intToString = num -> String.valueOf(num); System.out.println(intToString.apply(123));
-
Predicate: 接收一个输入参数,并返回一个布尔值结果。
Predicate<Integer> isEven = num -> num % 2 == 0; System.out.println(isEven.test(5)); // false
-
UnaryOperator: 继承自 Function<T, T>,表示一元操作符。
UnaryOperator<Integer> square = num -> num * num; System.out.println(square.apply(5)); // 25
自定义函数接口:只需确保接口中只有一个抽象方法即可。
@FunctionalInterface
interface MyFunctionalInterface {void myMethod();// 允许有默认方法和静态方法default void anotherMethod() {System.out.println("Default method");}
}// 使用自定义的函数接口
MyFunctionalInterface myFunc = () -> System.out.println("Hello Custom Functional Interface");
myFunc.myMethod();
myFunc.anotherMethod();
二、Lambda表达式简介
Lambda 表达式可以被视为匿名函数的一种声明方式,允许将函数作为方法参数传递,或者在需要函数式接口的地方使用。
基本结构:
// parameters:参数列表,可以为空或非空
// ->:箭头符号,分隔参数列表和Lambda表达式的主体
// expression:单行表达式作为 Lambda 主体
(parameters) -> expression// { statements; }:代码块作为 Lambda 主体,可以包含多条语句和返回语句
(parameters) -> { statements; }
表达式的特点:
- 简洁性和可读性: Lambda 表达式使代码更为简洁,尤其是在处理函数式接口时,省去了冗余的语法。
- 函数式编程风格: Lambda 表达式支持函数式编程,可以轻松地进行函数传递、方法引用和流式操作等。
- 闭包性: Lambda 表达式可以捕获其周围的变量,使得函数式编程中的状态管理更加灵活。
案例:通过 Lambda 表达式为
MathOperation
接口的operation
方法提供了四种不同的实现:加法、减法、乘法和除法。
- 接口的定义:
interface MathOperation {int operation(int a, int b);
}
- 使用 Lambda 表达式来实现这个接口,以便传递不同的数学运算逻辑:
public class LambdaDemo {public static void main(String[] args) {// Lambda 表达式实现加法MathOperation addition = (int a, int b) -> a + b;System.out.println("10 + 5 = " + operate(10, 5, addition));// Lambda 表达式实现减法MathOperation subtraction = (a, b) -> a - b;System.out.println("10 - 5 = " + operate(10, 5, subtraction));// Lambda 表达式实现乘法MathOperation multiplication = (int a, int b) -> { return a * b; };System.out.println("10 * 5 = " + operate(10, 5, multiplication));// Lambda 表达式实现除法MathOperation division = (a, b) -> a / b;System.out.println("10 / 5 = " + operate(10, 5, division));}private static int operate(int a, int b, MathOperation mathOperation) {return mathOperation.operation(a, b);}
}
三、Lambda表达式外部参数
Lambda 表达式有自己特定的作用域规则,可以捕获和访问其周围的变量, 可以随意引用外部变量,但如果外部变量是在当前作用域声明的,则一定不可以进行第二次赋值,哪怕是在 lambda 语句之后。
-
局部变量:Lambda 表达式可以访问它们所在方法的局部变量,但是这些变量必须是隐式最终或实际上是最终的(
final
)。这意味着变量一旦赋值后不再改变。Lambda 表达式内部不允许修改这些局部变量的值,否则编译器会报错。public class LambdaScopeDemo {public static void main(String[] args) {int num = 10; // 局部变量MathOperation addition = (int a, int b) -> {// num = 5; // 错误!Lambda 表达式不能修改局部变量的值// 这里访问了局部变量 numreturn a + b + num;};System.out.println(addition.operation(5, 3));} }
-
字段:Lambda 表达式可以访问外部类的字段(成员变量),包括实例字段和静态字段。
public class LambdaScopeDemo {private static int staticNum; // 静态字段private int instanceNum; // 实例字段public void testLambdaScope() {MathOperation addition = (int a, int b) -> {// 访问实例字段和静态字段int result = a + b + instanceNum + staticNum;return result;};System.out.println(addition.operation(5, 3));} }
-
接口的默认方法:Lambda 表达式可以访问接口中定义的默认方法,但不能访问接口中定义的实例字段。
四、Lambda范例
使用Lambda表达式时,常见的场景包括对集合的遍历、排序、过滤以及与函数式接口的结合使用。
常见的Java 8 Lambda表达式示例:
- 遍历集合
public static void main(String[] args) {List<String> names = new ArrayList<>();names.add("Alice");names.add("Bob");names.add("Charlie");// 使用 Lambda 表达式遍历集合names.forEach(name -> System.out.println(name));}
- 使用函数式接口进行计算
参考:二、Lambda表达式简介
- 使用函数式接口进行条件过滤
public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 使用 Lambda 表达式过滤偶数System.out.println("偶数:");filter(numbers, n -> n % 2 == 0);// 使用 Lambda 表达式过滤大于 5 的数System.out.println("大于 5 的数:");filter(numbers, n -> n > 5);}private static void filter(List<Integer> numbers, Predicate<Integer> condition) {for (Integer number : numbers) {if (condition.test(number)) {System.out.print(number + " ");}}System.out.println();}
- 使用Comparator进行集合排序
public static void main(String[] args) {List<String> names = new ArrayList<>();names.add("Alice");names.add("Bob");names.add("Charlie");// 使用 Lambda 表达式进行排序(根据字符串长度)names.sort((s1, s2) -> s1.length() - s2.length());// 输出排序后的结果names.forEach(name -> System.out.println(name));}
- 使用 Runnable 执行代码块
参考:五、Runnable Lambda表达式
五、Runnable Lambda表达式
使用 Lambda 表达式来简洁地实现
Runnable
接口的实例化。Runnable
接口是一个函数接口,它只包含一个抽象方法void run()
,用于定义一个可以由线程执行的任务。
- 匿名内部类(Java 7 及之前):
Runnable runnable = new Runnable() {@Overridepublic void run() {System.out.println("Running in a separate thread");}
};Thread thread = new Thread(runnable);
thread.start();
- Lambda 表达式(Java 8+):
Runnable runnable = () -> {System.out.println("Running in a separate thread");
};Thread thread = new Thread(runnable);
thread.start();
- 更简洁的方式:任务非常简单,可以进一步简化,直接将 Lambda 表达式作为参数传递给
Thread
的构造函数:
Thread thread = new Thread(() -> {System.out.println("Running in a separate thread");
});
thread.start();
这种方式避免了显式地声明 Runnable
变量,使代码更加紧凑和易读。
案例:
public static void main(String[] args) {// 使用 Lambda 表达式创建一个新的线程Thread thread = new Thread(() -> {for (int i = 0; i < 5; i++) {System.out.println("线程执行:" + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});// 启动线程thread.start();}
莫道君行早,更有早行人
相关文章:

Java 8的变革:函数式编程和Lambda表达式探索
文章目录 一、函数接口二、Lambda表达式简介三、Lambda表达式外部参数四、Lambda范例五、Runnable Lambda表达式 一、函数接口 函数接口是一个具有单个抽象方法的接口,接口设计主要是为了支持 Lambda 表达式和方法引用,使得 Java 能更方便地实现函数式编…...
Java集合框架的内部揭秘:List、Set与Map的深潜之旅
Java集合框架是一套强大的工具,为开发者提供了灵活的数据管理方式。本文将深入剖析List、Set和Map的内部机制,通过详细的示例和扩展讨论,带你领略这些数据容器的真谛。 一、List:有序序列的深度剖析 List接口是一个可以包含重复…...

爬虫(二)——爬虫的伪装
前言 本文是爬虫系列的第二篇文章,主要讲解关于爬虫的简单伪装,以及如何爬取B站的视频。建议先看完上一篇文章,再来看这一篇文章。要注意的是,本文介绍的方法只能爬取免费视频,会员视频是无法爬取的哦。 爬虫的伪装 …...

空安全编程的典范:Java 8中的安全应用指南
文章目录 一、Base64 编码解码1.1 基本的编码和解码1.2 URL 和文件名安全的编码解码器1.3 MIME Base64编码和解码 二、Optional类三、Nashorn JavaScript 一、Base64 编码解码 1.1 基本的编码和解码 Base64 编码: 使用 Base64.getEncoder().encodeToString(origin…...
Docker Machine 深入解析
Docker Machine 深入解析 引言 Docker Machine 是 Docker 生态系统中的一个重要工具,它简化了 Docker 容器环境的配置和管理过程。本文将深入探讨 Docker Machine 的概念、功能、使用场景以及如何在实际环境中高效利用它。 什么是 Docker Machine? Docker Machine 是一个…...

20.x86游戏实战-远线程注入的实现
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 工具下载: 链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…...

06MFC之对话框--重绘元文件
文章目录 实现示例展示需要绘制的窗口/位置控件位置更新下一次示例粗细滑动部分更新重绘元文件(窗口变化内容消失)方法一:使用元文件方法二:兼容设备方法三:使用自定义类存储绘图数据除画笔外功能处理画笔功能处理保存前面画的线及色彩实现示例展示 需要绘制的窗口/位置 …...

鼠标的发明和鼠标“变形记”
注:机翻,未校对。 Who Invented the Computer Mouse? 谁发明了电脑鼠标? It was technology visionary and inventor Douglas Engelbart (January 30, 1925 – July 2, 2013) who revolutionized the way computers worked, turning it fr…...

快捷:通过胶水语言实现工作中测试流程并行、加速
通过胶水语言实现工作中测试流程并行、加速 通过胶水语言实现工作中测试流程并行、加速工作场景(背景)问题抽象(挑战)如何做(行动)获得了什么(结果)后记相关资源 通过胶水语言实现工…...

MySQL 和 PostgreSQL,我到底选择哪个?
MySQL 和 PostgreSQL 是两个广泛使用的关系型数据库管理系统(RDBMS)。它们都具有强大的功能和广泛的社区支持,但在某些方面存在一些差异。本文将详细比较 MySQL 和 PostgreSQL,包括它们的特点、性能、扩展性、安全性以及适用场景等…...
Java —— 内部类
Java内部类 1.什么是内部类? 将一个类A定义在另一个类B里面,里面的类A就称为内部类(InnerClass),类B则称为外部类(OuterClass)。 2.为什么需要内部类? 具体来说,当一…...

高职院校人工智能人才培养成果导向系统构建、实施要点与评量方法
一、引言 近年来,人工智能技术在全球范围内迅速发展,对各行各业产生了深远的影响。高职院校作为培养高技能人才的重要基地,肩负着培养人工智能领域专业人才的重任。为了适应社会对人工智能人才的需求,高职院校需要构建一套科学、…...
ffmpeg中的超时控制
在FFmpeg库中,很多函数没有直接的参数可以设置超时。 那么有哪些函数可以通过设置 AVFormatContext 的 interrupt_callback 来实现超时控制? avformat_open_input: 打开输入文件或流。这个函数会阻塞,尤其是在网络流的情况下&…...

搜维尔科技:【研究】触觉技术将在5年内以8种方式改变人们的世界
触觉技术在过去几年中发展迅猛,大大提高了反馈的精确度和真实度。其应用产生了真正的影响,数百家公司和企业都集成了触觉技术来增强培训和研究模拟。 虽然触觉技术主要用于 B2B 层面,但触觉技术可能会彻底改变我们的生活,尤其是通…...

项目收获总结--MyBatis的知识收获
MyBatis的知识收获 一、概述二、获取自动生成的(主)键值三、将sql执行结果封装为目标返回对象的方式和原理四、延迟加载实现原理五、批量插入六、自带分页与分页插件原理七、Mapper(Dao)接口与XML映射文件关系八、模糊查询like语句九、#{}和${}的区别十、二级缓存案例实战 一、…...
数据库管理-第221期 Oracle的高可用-04(20240717)
数据库管理221期 2024-07-17 数据库管理-第221期 Oracle的高可用-04(20240717)1 ADG2 连接配置2.1 TNS2.2 JDBC2.3 JAVA连接池2.3.1 Oracle UCP2.3.2 应用连接池基础配置 总结 数据库管理-第221期 Oracle的高可用-04(20240717) 作…...

navicat15已连接忘记密码
1.导出链接 2.使用文本打开 connections.ncx UserName"root" PasswordXXXX 3.复制加密密码,在线解密 代码在线运行 - 在线工具 php解密代码 <?php class NavicatPassword {protected $version 0;protected $aesKey libcckeylibcckey;protected…...

企业管理必备:学会寻找客户绝佳方法。
无论是日常沟通、工作交流,还是社交娱乐,微信都扮演着重要的角色。而在微信的使用过程中,添加好友是一项基本而重要的操作,但是您真的会添加微信好友吗? 试试这个神器——微信管理系统,下面分享它快速加客…...

昇思25天学习打卡营第29天 | 文本解码原理--以MindNLP为例
今天是29天,学习了文本解码原理--以MindNLP为例。 MindNLP 是一个基于 MindSpore 的开源自然语言处理(NLP)库。它具有以下特点: 支持多种 NLP 任务:如语言模型、机器翻译、问答、情感分析、序列标记、摘要等ÿ…...

元服务体验-服务发现
服务发现,无论线上或线下的方式都可以发现元服务。 线上:基于用户意图。从精准意图的搜索、用户事件触发的推荐到主动探索等场景。用户可以在设备的负一屏、全局搜索、应用市场、桌面等场景发现元服务。 线下:用户在 HarmonyOS Connect标签…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...