JDK8新特性之Lambda表达式快速入门
目录标题
- 为什么使用 Lambda 表达式
- 示例一:先看一个常用排序类Comparator的示例
- 示例二:筛选员工数据的示例
- 传统方式实现的示例
- 策略模式优化的示例
- Lambda 基础语法
- 语法格式一:无参数,无返回值
- 语法格式二:有一个参数,并且无返回值
- 语法格式三:若只有一个参数,小括号可以省略不写
- 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
- 语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
- 语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写
- Lambda 表达式需要“函数式接口”的支持
- JDK8自带的函数式接口
为什么使用 Lambda 表达式
示例一:先看一个常用排序类Comparator的示例
Comparator<String> com = new Comparator<String>(){@Overridepublic int compare(String o1, String o2) {return Integer.compare(o1.length(), o2.length());}
};
TreeSet<String> ts = new TreeSet<>(com);
代码再简化一点,匿名内部类写法:
TreeSet<String> ts = new TreeSet<>(new Comparator<String>(){@Overridepublic int compare(String o1, String o2) {return Integer.compare(o1.length(), o2.length());}
});
简化后还是有代码冗余,实际有用的代码就“Integer.compare(o1.length(), o2.length())” 这一行。
这时Lambda 表达式闪亮登场:
Comparator<String> com = (o1, o2) -> Integer.compare(o1.length(), o2.length());
TreeSet<String> ts = new TreeSet<>(com);
代码是不是简洁很多了。
示例二:筛选员工数据的示例
员工类:
public class Employee {private int id;private String name;private int age;private double salary;// get()、set()、hashCode()、equals()、toString()省略
}
现在有一批员工数据:
List<Employee> emps = Arrays.asList(new Employee(101, "张三", 18, 9999.99),new Employee(102, "李四", 59, 6666.66),new Employee(103, "王五", 28, 3333.33),new Employee(104, "赵六", 8, 7777.77),new Employee(105, "田七", 38, 5555.55)
);
传统方式实现的示例
有以下业务需求,通过传统方式实现如下:
/*** 需求1:获取公司中年龄小于 35 岁的员工信息* @param emps* @return*/
public List<Employee> filterEmployeeAge(List<Employee> emps){List<Employee> list = new ArrayList<>();for (Employee emp : emps) {if(emp.getAge() <= 35){list.add(emp);}}return list;
}/*** 需求2:获取公司中工资大于 5000 的员工信息* @param emps* @return*/
public List<Employee> filterEmployeeSalary(List<Employee> emps){List<Employee> list = new ArrayList<>();for (Employee emp : emps) {if(emp.getSalary() >= 5000){list.add(emp);}}return list;
}
仔细观察几个方法发现只有if()判断一行代码不一样,其他代码都相同。
优化思路:提取封装变化的部分,相同代码复用,另外还要考虑再有类似需求的扩展性,比如按性别过滤、按姓氏过滤等。此时我们会想到一种设计模式:策略模式。
策略模式优化的示例
定义顶层接口:
@FunctionalInterface
public interface MyPredicate<T> {boolean test(T t);
}
根据业务需求,定义接口的实现类,也即上面变化的部分:
/*** 按年龄过滤的类*/
public class FilterEmployeeForAge implements MyPredicate<Employee>{@Overridepublic boolean test(Employee t) {return t.getAge() <= 35;}
}/*** 按工资过滤的类*/
public class FilterEmployeeForSalary implements MyPredicate<Employee> {@Overridepublic boolean test(Employee t) {return t.getSalary() >= 5000;}
}
相同的部分,也即不变的部分:
public List<Employee> filterEmployee(List<Employee> emps, MyPredicate<Employee> predicate){List<Employee> list = new ArrayList<>();for (Employee employee : emps) {if(predicate.test(employee)){ //这一行具体实现类实现list.add(employee);}}return list;
}
策略模式实现上面业务需求:
//需求1:获取公司中年龄小于 35 的员工信息
List<Employee> list = filterEmployee(emps, new FilterEmployeeForAge());
for (Employee employee : list) {System.out.println(employee);
}//需求2:获取公司中工资大于 5000 的员工信息
List<Employee> list2 = filterEmployee(emps, new FilterEmployeeForSalary());
for (Employee employee : list2) {System.out.println(employee);
}
这样,业务代码过滤员工数据时就简洁了很多,也满足了代码的开闭原则。
如果以后有其他过滤员工信息的需求,比如按性别过滤的需求,我们再新建一个过滤实现类即可。
但如果过滤的业务需求很多,那么要新建的过滤实现类也要很多。可以不新建那么多小类吗?
可以,方式一:匿名内部类
List<Employee> list = filterEmployee(emps, new MyPredicate<Employee>() {@Overridepublic boolean test(Employee t) {return t.getSalary() >= 5000;}
});
for (Employee employee : list) {System.out.println(employee);
}
方式二:Lambda表达式
List<Employee> list = filterEmployee(emps, (e) -> e.getSalary() >= 5000);
list.forEach(System.out::println);
对比一下,Lambda表达式的方式是不是代码更简洁清晰。
Lambda 基础语法
Java8中引入了一个新的操作符 “->”, 该操作符称为箭头操作符或 Lambda 操作符。
箭头操作符将 Lambda 表达式拆分成两部分:
- 左侧:Lambda 表达式的参数列表
- 右侧:Lambda 表达式中所需执行的功能, 即实现类的方法体
语法格式一:无参数,无返回值
() -> System.out.println(“Hello Lambda!”);
int num = 0;//jdk1.7及以前必须加final
Runnable r = new Runnable() {@Overridepublic void run() {System.out.println("Hello World!" + num);}
};
r.run();Runnable r1 = () -> System.out.println("Hello Lambda!" + num);
r1.run();
语法格式二:有一个参数,并且无返回值
Consumer<String> con = (x) -> System.out.println(x);
con.accept("Hello Lambda!");
语法格式三:若只有一个参数,小括号可以省略不写
Consumer<String> con = x -> System.out.println(x);
con.accept("Hello Lambda!");
语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句
有多条语句时,方法体加**{},有返回值加return**。
Comparator<Integer> com = (x, y) -> {System.out.println("函数式接口");return Integer.compare(x, y);
};
语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写
因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);
//根据前面Comparator<Integer>里指定的Integer推断的
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
String[] arr = {“aaa”, “bbb”, “ccc”}; //值简写,也是根据前面String类型推断的
List< String> list = new ArrayList<>(); //ArrayList<>里没写String,也是根据List< String>里推断出来的
Lambda 表达式需要“函数式接口”的支持
函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。
可以使用注 @FunctionalInterface注解修饰,该注解可以检查是否是函数式接口,比如接口类里定义了2个接口方法,就会提示错误。
JDK8自带的函数式接口
| 函数式接口 | 参数类型 | 返回类型 | 用途 |
|---|---|---|---|
| Consumer< T> | T | void | 对类型为T的对象应用操作,包含方法:void accept(T t) |
| Supplier< T> 供给型接口 | 无 | T | 返回类型为T的对象,包含方法:T get(); |
| Function< T, R> 函数型接口 | T | R | 对类型为T的对象应用操作,并返回结果。结果是R类型的对象。包含方法:R apply(T t); |
| Predicate< T> 断定型接口 | T | boolean | 确定类型为T的对象是否满足某约束,并返回boolean 值。包含方法boolean test(T t); |
示例:
@Test
public void test7(){Integer num = operation2(100, (x) -> x * x);System.out.println(num);System.out.println(operation2(200, (y) -> y + 200));
}public Integer operation2(Integer num, Function<Integer, Integer> fun){return fun.apply(num);
}
相关文章:
JDK8新特性之Lambda表达式快速入门
目录标题 为什么使用 Lambda 表达式示例一:先看一个常用排序类Comparator的示例示例二:筛选员工数据的示例传统方式实现的示例策略模式优化的示例 Lambda 基础语法语法格式一:无参数,无返回值语法格式二:有一个参数&am…...
QEMU源码全解析 —— CPU虚拟化(14)
接前一篇文章: 本文内容参考: 《趣谈Linux操作系统》 —— 刘超,极客时间 《QEMU/KVM》源码解析与应用 —— 李强,机械工业出版社 《深度探索Linux系统虚拟化原理与实现》—— 王柏生 谢广军, 机械工业出版社 特此致谢! 三、KVM模块初始化介绍 2. KVM模块初始化 KV…...
libsoup的简单使用
基于GLib和libsoup的简单Web服务器示例,它可以处理静态HTML文件和动态JSON请求,并展示如何获取URL参数。 步骤: 初始化GLib和libsoup。创建一个处理静态HTML文件的处理器。创建一个处理动态JSON请求的处理器。获取URL参数并在JSON响应中返回…...
electron项目搭建
前言:electron是一个跨平台桌面端应用开发工具。它将整个系统内容分为主进程和渲染进程两个部分(你可以粗略的理解为electron项目开启了两个服务器,一个渲染页面另一个处理electron窗口内容)。这两个"服务器"之间通过JS Bridge进行通信(即&…...
【CVPR2024】Efficient LoFTR: 高效的 LoFTR:具有类似稀疏的速度的半密集局部特征匹配
Efficient LoFTR: 高效的 LoFTR:具有类似稀疏的速度的半密集局部特征匹配 Efficient LoFTR realtime_demo 0.摘要 \qquad 我们提出了一种新的方法来有效地产生跨图像的半密集匹配。以往的无探测器匹配器LoFTR在处理大视点变化和纹理差的场景下表现出了出色的匹配能力…...
【Golang 面试 - 基础题】每日 5 题(九)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/UWz06 📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏…...
《程序猿入职必会(4) · Vue 完成 CURD 案例 》
📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗 🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数…...
编程技巧:如何优雅地合并两个有序数组?
目录 题目引用描述1.直接合并 排序2.指针3.后逆向双指针进阶:你可以设计实现一个时间复杂度为 O(m n) 的算法解决此问题吗?总结 题目 来自力扣 引用 合并两个有序数组 给你两个按 **非递减顺序 **排列的整数数组 nums1 和 nums2,另有两个整…...
Vue组件库移动端预览实现原理
引言 大家如果使用过移动端组件库(比如:Vant),会发现在网站右侧有一个手机端的预览效果。 而且这个手机端预览的内容和外面的组件代码演示是同步的,切换组件的时候,移动端预览的内容也会发生相应的变化。 …...
FastAPI(七十五)实战开发《在线课程学习系统》接口开发-- 创建课程
源码见:"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 上次我们分享了,FastAPI(七十四)实战开发《在线课程学习系统》接口开发-- 删除留言 从本篇文章开始,…...
【C++】 条件变量实现线程同步示例
在做一些比较大的项目的时候,需要实现线程同步, 这里结合一个小示例,进行线程同步的讲解 问题定义 以下是一个使用 C 多线程和条件变量的示例,展示了线程 A 接收一个 enable 信号并通知线程 B 开始工作。线程 B 在开始工作之前…...
linux下载redis安装并指定配置文件启动
linux下载redis并安装启动: cd /usr/local/src 下载redis压缩包 wget http://download.redis.io/releases/redis-6.2.6.tar.gz 解压 tar -xzf redis-6.2.6.tar.gz 编译和安装redis make make install 安装完成后进入 redis 安装目录 cd /usr/local/bin 修改…...
线性结构、线性表、顺序表、链表、头插法、尾插法、中间插入或删除一个节点
梳理几个名词: 逻辑地址:就是说是第几个元素。 物理地址:也就是存储地址,在计算机里具体存放的位置。 线性表的存储结构分为: (1)顺序存储结构:将数据依次存储在连续的整块物理空…...
C# Task.WaitAll 的用法
目录 简介 1.WaitAll(Task[], Int32, CancellationToken) 2.WaitAll(Task[]) 3.WaitAll(Task[], Int32) 4.WaitAll(Task[], CancellationToken) 5.WaitAll(Task[], TimeSpan) 结束 简介 Task.WaitAll 是 C# 中用于并行编程的一个的方法,它属于 System.Threa…...
vue2 前端实现pdf在线预览(无插件版)
toFielDetail()是点击预览的方法,getOfficialFile是获取文件流的接口正常定义即可: export function getOfficialFile(query) {return request({url: /dataAsset/projectassess/getOfficialFile,method: get,params: query,}); } 调用接口的页面需要引用…...
排序XXXXXXXXX
信息学奥赛|常见排序算法总结(C+) - 腾讯云开发者社区-腾讯云 (tencent.com) https://cloud.tencent.com/developer/news/975232 常用序号层级排序 一、序号 序号Sequence Number,有顺序的号码,如数字序号…...
【文件解析漏洞】实战详解!
漏洞描述: 文件解析漏洞是由于中间件错误的将任意格式的文件解析成网页可执行文件,配合文件上传漏洞进行GetShell的漏洞! IIS解析漏洞: IIS6.X: 方式一:目录解析 在网站下建立文件夹的名字为.asp/.asa 的文件夹,其目…...
【杂谈】学会让你节省三秒钟——Dev-c++的缺省源
【杂谈】学会让你节省三秒钟——Dev-c的缺省源 1.前言2.缺省源的介绍3.注意 1.前言 你是否在为每次写程序都要自己手打一遍框架而感到苦恼?为什么大佬的Dev-C一新建文件就会自动出现程序框架?看完这篇文章,让你也能成为大佬,不用再…...
推荐一款前端滑动验证码插件(Vue、uniapp)
uniapp版本:滑块拼图验证码,有后端,简单几步即可实现,小程序、h5都可以用 - DCloud 插件市场 Vue版本及cdn版本可以查阅文档: 行为验证 | Poster 文档 示例代码: <template><view id"app&…...
【Git】git stash
目录 基本概念参数详解listshowsavepushpop|applydropclearbranch 参考文章 Git的stash命令是一个非常实用的功能,它允许开发者临时保存工作目录和暂存区的更改,以便能够切换到其他分支或进行其他操作,而不会丢失当前的修改。以下是git stash…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
