Lambda表达式学习笔记
Lambda基础语法
Java8中引入了一个新的操作符“ -> ”,该操作符被称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分成两部分:
- 左侧:Lambda表达式的参数列表
- 右侧:Lambda表达式中所需要执行的功能,即Lambda体
Lambda表达式常见的五种语法如下:
- 语法格式一:无参数,无返回值 (如Runable接口中的run方法)
@Test
public void test01(){
Runnable run01 = new Runnable() {
@Override
public void run() {
System.out.println("通过匿名内部函数实现!");
}
};
run01.run();
Runnable run02 =() -> System.out.println("Hello Lambda!");
run02.run();
}
2. 语法格式二:有一个参数,无返回值 (如Java8中的Consumer接口)
@Test
public void test02(){
Consumer con01 = (x) -> System.out.println(x);
//若只有一个参数,小括号可以省略不写
Consumer con02 =x -> System.out.println(x);
//调用抽象方法
con01.accept("使用Lambda表达式,实现抽象方法,输出参数的值");
con02.accept("若只有一个参数,小括号可以省略不写");
}
3. 语法格式三:有两个以上参数,有返回值,并且Lambda体中有多条语句,大括号必须写
@Test
public void test03(){
Comparator<Integer> com = (x, y) -> {
System.out.println("函数式接口");
return Integer.compare(x,y);
};
int compare = com.compare(3, 6);
System.out.println(compare);//输出结果为:函数式接口 -1
}
4. 语法格式四:若Lambda体中只有一条语句,return 和 大括号 都可以省略不写
@Test
public void test04(){
Comparator<Integer> com = (x, y) -> Integer.compare(x,y);
int compare = com.compare(3, 6);
System.out.println(compare); // 输出结果为: -1
}
5. 语法格式五:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器可以通过上下文推断出数据类型,即“类型推断”
@Test
public void test05(){
Comparator<Integer> com = (Integer x,Integer y) -> Integer.compare(x,y);
int compare = com.compare(3, 6);
System.out.println(compare); // 输出结果为: -1
}
Lambad表达式需要“函数式接口“的支持
函数式接口:接口中只有一个抽象方法的接口,称为函数式接口,可以使用注解@FunctionalInterface修饰,检查是否是函数式接口
注意:在jdk1.8之前,在局部内部类中,使用了同级别的局部变量,该局部变量必须使用final修饰,JDK1.8之后,该局部变量被默认使用了final修饰,仍然不允许被修改,不需要我们手动去加了
Java8 内置的四大核心函数式接口
- 消费型接口
@FunctionalInterface
public interface Consumer<T> {
//一个参数,无返回值
void accept(T t);
}
- 供给型接口
@FunctionalInterface
public interface Supplier<T> {
//无参数,有返回值
T get();
}
- 函数性接口
@FunctionalInterface
public interface Function<T, R> {
// T代表参数,R代表返回值
R apply(T t);
}
- 断言型接口(用作一些判断操作)
@FunctionalInterface
public interface Predicate<T> {
//一个参数,返回值为boolean类型,常用来做一些判断操作
boolean test(T t);
}
下面对Java8提供四大核心函数式接口,进行简单的测试运用:
- 消费型接口测试
@Test
public void test06(){
//使用Lambda表达式,对Consumer接口中的accept()进行了具体实现
happy(10000.00,(money) -> System.out.println("今天用了10000元买了台Mac笔记本电脑"));
}
/**
* 自定义方法调用Consumer接口的抽象方法
* @param money
* @param consumer
*/
public void happy(Double money,Consumer<Double> consumer){
consumer.accept(money);
}
- 供给型接口测试
@Test
public void test07(){
//获取10个100以内的随机数
List<Integer> numList = getNumList(10,() -> (int)(Math.random()*100));
for(Integer num: numList){
System.out.println(num);
}
}
//需求:产生指定个数的整数,并放入集合中
public List<Integer> getNumList(int num,Supplier<Integer> sup){
List<Integer> list = new ArrayList<>();
for(int i=0;i<num;i++){
Integer n = sup.get();
list.add(n);
}
return list;
}
- 函数型接口测试
//函数型接口:可以对参数进行一些操作,然后返回操作结果
@Test
public void test08(){
//由于Lambad体中只有一条语句,这里return 和 大括号 都省略了
String newStr = strHandler("函数型接口测试",(str) -> str.substring(3,str.length()));
System.out.println(newStr);// 输出结果为: 接口测试
}
//需求:用于处理字符串
public String strHandler(String str,Function<String,String> fun){
return fun.apply(str);
}
- 断言型接口
@Test
public void test09(){
List<String> list = Arrays.asList("hello","Lambda","easy","OK");
//获取字符串长度大于4的集合
List<String> strList = filterStr(list,(s) -> {return s.length()>4;});
System.out.println(strList); // 输出结果为:[hello, Lambda]
}
//将满足条件的字符串,放入集合中
public List<String> filterStr(List<String> list,Predicate<String> pre){
List<String> strList = new ArrayList<>();
for(String str:list){
//调用断言型接口中的方法,判断是否满足条件
if(pre.test(str)){
strList.add(str);
}
}
return strList;
}
方法引用
若Lambda 体中的内容有方法已经实现了,我们可以使用“方法引用”(可以理解为Lambda表达式的另一种表现形式)。
主要有三种语法格式:
- 语法格式一: 对象::实例方法名
- 语法格式二: 类名::静态方法名
- 语法格式三: 类名::实例方法名
条件:Lambda体中调用方法的参数列表和返回值类型,要与 函数式接口中抽象方法的参数列表和返回值类型保持一致
下面我们对方法引用的三种语法格式,使用代码来看看是如何使用的吧:
//对象::实例方法
@Test
public void test10(){
//使用Lambda表达式实现接口中的抽象方法
Consumer<String> con = (x) -> System.out.println(x);
con.accept("abcdef");
//使用 方法引用 的形式,实现接口中的抽象方法
//这里的 System.out 实际上是PrintStream的类型的匿名对象
//System.out::println; 也可以写成 PrintStream ps1 = System.out; ps1::println;
Consumer<String> con2 = System.out::println;
con2.accept("abcdef");
}
这里为了更好看方法引用的语法格式,我们可以创建一个Emp实体类:如下
public class Emp {
private Integer id;
private String name;
public Emp() {
}
public Emp(Integer id) {
this.id = id;
}
public Emp(String name) {
this.name = name;
}
public Emp(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
接下来我们再使用Emp实体类的对象,通过 对象::实例方法 这种语法格式进行练习
@Test
public void test11(){
Emp emp = new Emp();
//使用Lambda表达式实现Supplier接口中的抽象方法
Supplier<String> sup = () -> emp.getName();
String str = sup.get();
System.out.println(str);
//使用方法引用代替Lambda表达式进行实现
//注意:这里的getName()的参数列表和返回值类型,和Supplier接口中的get()的参数列表和返回值类型是保持一致的
Supplier<String> sup2 = emp::getName;
String name = sup2.get();
System.out.println(name);
}
语法格式二:类名::静态方法名 的具体应用
@Test
public void test12(){
Comparator<Integer> com01 = (x,y) -> Integer.compare(x,y);
int compare01 = com01.compare(10, 8);
System.out.println("通过Lambda表达式的比较结果为:"+compare01);
//类名::静态方法名
Comparator<Integer> com02 = Integer::compare;
int compare02 = com02.compare(10, 8);
System.out.println("通过方法引用实现的比较结果为:"+compare02);
}
语法格式三:类名::实例方法名
使用该种语法格式时,必须要注意:若Lambda表达式参数列表中的第一个参数是 实例方法的调用者,而第二个参数是实例方法的参数时,则可以使用ClassName::method。
@Test
public void test13(){
BiPredicate<String,String> bp01 = (x,y) -> x.equals(y);
boolean test01 = bp01.test("hello", "hello");
System.out.println("通过Lambda表达式的比较结果为:"+test01);//输出结果:通过Lambda表达式的比较结果为:true
BiPredicate<String,String> bp02 = String::equals;
boolean test02 = bp02.test("hello", "hello");
System.out.println("通过方法引用实现的比较结果为:"+test02); //输出结果:通过方法引用实现的比较结果为:true
}
构造器引用
格式:ClassName::new
注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致
@Test
public void test14(){
Supplier<Emp> sup = () -> new Emp();
//构造器引用方式
//调用的是无参构造:由于需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致,这里供给型结构Supplier中的get()是没有参数列表,所以调用的是无参构造
Supplier<Emp> sup02 = Emp::new;
Emp emp = sup02.get();
System.out.println(emp);
}
@Test
public void test15(){
Function<Integer,Emp> fun = (x) -> new Emp(x);
//调用的是带一个参数的构造:因为函数型接口Function中的apply()有一个参数
Function<Integer,Emp> fun02 = Emp::new;
Emp emp = fun02.apply(101);
System.out.println(emp);
}
数组引用
语法格式:数组类型::new
@Test
public void test16(){
//Lambda表达式实现
Function<Integer,String[]> fun01 = (x) -> new String[x];
String[] strs = fun01.apply(10);
System.out.println(strs.length); //输出结果: 10
//数组引用: 数组类型::new;
Function<Integer,String[]> fun02 = String[]::new;
String[] strs2 =fun02.apply(20);
System.out.println(strs2.length);//输出结果: 20
}
Lambda表达式学习笔记的更多相关文章
- C# Lambda表达式学习笔记
本笔记摘抄自:https://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html,记录一下学习过程以备后续查用. 一.Lambda ...
- java lambda表达式学习笔记
lambda是函数式编程(FP,functional program),在java8中引入,而C#很早之前就有了.在java中lambda表达式是'->',在C#中是‘=>’. 杜甫说:射 ...
- lambda 表达式学习笔记
在Java中传递一个代码段并不容易,不能直接传递代码段.Java是一个面向对象语言,所以必须构造一个对象,这个对象的类需要一个方法能包含所需的代码.lambda的出现有效的解决这个问题,让代码变得更加 ...
- python函数和lambda表达式学习笔记
1. python函数 不同于其他语言,python支持函数返回多个值 为函数提供说明文档:help(函数名)或者函数名.__doc__ def str_max(str1, str2): ''' 比较 ...
- C# Lambda 表达式学习之(三):动态构建类似于 c => c.Age == null || c.Age > 18 的表达式
可能你还感兴趣: 1. C# Lambda 表达式学习之(一):得到一个类的字段(Field)或属性(Property)名,强类型得到 2. C# Lambda 表达式学习之(二):LambdaExp ...
- C# Lambda 表达式学习之(四):动态构建类似于 c => c.Age == 2 || c.Age == 5 || c => c.Age == 17 等等一个或多个 OrElse 的表达式
可能你还感兴趣: 1. C# Lambda 表达式学习之(一):得到一个类的字段(Field)或属性(Property)名,强类型得到 2. C# Lambda 表达式学习之(二):LambdaExp ...
- Lamda表达式学习笔记二
Lamda表达式学习笔记二 lamda表达式----方法引用 上一篇讲到Lamda体就是对函数式接口方法的实现 ,在方法体中我们可能会引用其他方法实现逻辑,所以在lamda体中我们可以直接引用器方法 ...
- Lamda表达式学习笔记一
Lamda表达式学习笔记一 一.Lamda语法诠释 三傻大闹宝莱坞的主人公兰彻说的一句话让我映像深刻:用简单的语言来表达同样的意 我并不是说书上的定义怎么怎么不对,而是应该理解书本上的定义,并用简单的 ...
- java 8 中lambda表达式学习
转自 http://blog.csdn.net/renfufei/article/details/24600507 http://www.jdon.com/idea/java/10-example-o ...
随机推荐
- 学习和使用 Styled Layer Descriptor SLD样式文件
1. SLD 文件大致作用,可以浏览下示意图: 点要素的符号化:http://docs.geoserver.org/stable/en/user/styling/sld-cookbook/points ...
- 吴裕雄--天生自然python编程:turtle模块绘图(3)
turtle(海龟)是Python重要的标准库之一,它能够进行基本的图形绘制.turtle图形绘制的概念诞生于1969年,成功应用于LOGO编程语言. turtle库绘制图形有一个基本框架:一个小海龟 ...
- 吴裕雄--天生自然 人工智能机器学习实战代码:ELASTICNET回归
import numpy as np import matplotlib.pyplot as plt from matplotlib import cm from mpl_toolkits.mplot ...
- mysql启动报错ERROR! The server quit without updating PID file处理
从其它服务器拷贝编译安装后的MySQL5.7目录后启动时报错如下: ERROR! The server quit without updating PID file(/path/to/XXX.pid) ...
- Python实现链表倒序(带头指针)
class ListNode(object): def __init__(self, x): self.val = x self.next = None def reverseList(self, h ...
- windows7 64位系统下无法运行ipython
windows7 64位系统下无法运行ipython | Creator 导航 导航 博客 分类 标签 友链 关于 大专栏 windows7 64位系统下无法运行ipythontent-post L ...
- MySQL 的 RowNum 实现(排行榜计算用户排名)
1. 计算用户排名最高效的方法 例如:通过用户分享个数排名,那么自己的排名就是:比自己分享数多的用户个数 + 1 ' and `count` > '自己分享个数' 缺点:当多个用户分享个数相同的 ...
- 事务以及Spring的事务管理
一.什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行 二.事务的特性(ACID) 原子性: 事务是最小的执行单位,不允许分割.事务的原子性确保动作要么全部完成,要么完全不起作用: 一致性 ...
- 快速入门和查询Python
评分: 4.5 作者: Ryan Lu 类别:Python 时间: 1. 注释 三种方式: 单行注释以 # 开头 多行注释用三个单引号 ''' 将注释括起来 多行注释用三个双引号 "&quo ...
- Nginx使用和配置
概要: Nginx 简介 Nginx 架构说明 Nginx 基础配置与使用 Nginx 反向代理与负载均衡 Nginx 实现高速缓存 Nginx 性能参数调优 一.Nginx 简介与安装 Nginx ...