学习lambda表达式和函数式接口
中间方法和终结方法
中间方法返回值是一个流,可以继续链式调用
终结方法返回值为空,不能再调用其他方法
终结方法
- forEach 遍历所有元素,可以添加操作
- count 返回一个long型数据,为元素数量
- toArray 收集流中数据,放入数组中
- 无参调用,返回的是Obj数组
- 有参调用,指定数组类型
注意,括号内那老长几行,都是toArray方法的参数,该对象内函数的返回值是一个预计类型的数组。 - 拉姆达表达式形式:
拉姆达表达式 ()->{} 小括号内对应上面IntFunction内apply方法的参数
- 无参调用,返回的是Obj数组
- collect 收集数据到集合中
若是收集到set集合中,则会自动去重- 收集到map中 注意键不能重复,否则会报错
- 拉姆达表达式形式 (形参,箭头,方法体)
- 拉姆达表达式形式 (形参,箭头,方法体)
- 收集到map中 注意键不能重复,否则会报错
总结
宋红康 java jdk8 和 17 的新特性
04年java5.0 重量级
java8.0 LTS长期支持版本
LTS长期支持版本,在支持周期内官方会持续维护,更新bug。非LTS在新版本出现后停止更新。
java9.0开始每半年更新
特性驱动发布周期,转变为以时间驱动
java9开始,api可能直接被删除
想要测试其他版本的特性,建议在IDEA的Modules选择对应版本的jdk
1996 jdk1.0
2004 jdk5.0
2014 jdk8.0 LTS
2017 jdk9.0 自此,每半年发布新版本
2018 jdk11 LTS
2021 jdk17 LTS
如何关注新特性?
新的语法规则?(多关注)
自动装拆箱,注解,enus,lambda表达式,方法引用
增加,过时,删除API
StringBuilder 5.0新增
底层优化,JVM参数调整,GC变化,内存结构(jdk8 永久代 -> 元空间)
lamada表达式
快速入门:
Runable接口只有一个方法
Comparator接口同样只有一个方法,泛型Integer指定参数类型
lambda表达式改写
方法引用改写
格式
todo:只适用于接口只有一个方法的场景?抽象方法?函数式接口?
(o1,o2) -> Integer.compare(o1,o2);
-> lambda操作符,箭头操作符
->左侧 ()重写接口的抽象方法的形参列表。
->右边 {} lambda体,对应重写的方法的方法体。(若只有一行大括号可以省略,return 也可以省略)
无参,无返回值
一个参数,无返回值
数据类型可由编译器推断————“类型推断”,省略数据类型
类型推断
数组类型推断
若形参列表只有一个参数,小括号可以省略
两个或者两个以上的参数,多条执行语句,且可以有返回值
Lambda体只有一条语句时,return 与 大括号 均可以省略(必须一起省略)
本质
左边声明一个对象
左边是一个接口,只有一个抽象方法
Lambda表达式充当了接口的实现类的对象
Lambda表达式也可以看做一个匿名方法
--> 万事万物皆对象
函数式接口
什么是函数式接口
若一个接口只声明了一个抽象方法,则此接口称为函数式接口。
只有给函数式接口提供实现类对象时,才能使用Lambda表达式
函数式接口的API
java.util.function包下,声明函数式接口
常见四个函数式接口
方法引用
理解
看作是基于Lambda表达式的进一步刻画
当需要提供一个函数式接口的实例时,可以使用Lambda表达式提供实例。
当满足一定条件时,可以使用方法应用和构造器引用替换Lambda表达式
本质
方法引用作为函数式接口的实例 ---> 万事万物皆对象
格式
类或对象 :: 方法名
函数式接口的实现方法里,只有一行语句,调用了一个方法,调用的方法与函数式接口的方法,形参与返回值类型均相同或一致,此时,可以看做调用的方法 是对 函数式接口定义方法的替换,于是可以用方法引用。
(参数列表一致即可,如int 与 Integer可以兼容,满足自动装拆箱
或者
参数的逆变:
逆变(Contravariance) 是指参数类型的一种转换规则,允许函数式接口的参数类型比实际实现方法的参数类型更宽泛(即父类)。
但是同时,也支持 抽象方法参数是子类,引用方法参数是父类的情况,这不涉及到逆变,而是通过多态机制。
抽象方法参数是父类,引用方法参数是子类,虽然可能导致TypeCastException,但是为了灵活性考量
返回值的协变:子类方法的返回值类型可以是父类方法返回值类型的子类
抽象方法返回值是父类,被引用方法返回值是子类
)
情况1:对象 :: 实例方法(非静态方法)
System.out 是对象 println()是一个实例方法
示例二:
要求:函数式接口抽象方法a的实现为 调用对象P的方法b,且方法a与方法b,形参列表与返回值类型均相同(参数列表一致即可,如int 与 Integer可以兼容),故可以使用方法b对方法a替换,这种做法称为方法引用。
情况2:类 :: 静态方法
要求:函数式接口抽象方法a的实现为 调用类C的静态方法b,且方法a与方法b,形参列表与返回值类型均相同,故可以使用静态方法b对方法a替换。
情况3:类 :: 实例方法
要求:此时,返回值类型相同,形参列表不同,抽象方法参数个数为n,被引用方法参数个数为n-1,且抽象方法第一个参数恰好是被引用方法的调用者。后n-1个参数类型一致。
示例二:
示例三:
构造器引用
示例二:function的apply,传一个类型,返回一个类型
示例三:BiFunction,二元函数
格式
类名 :: new
说明
调用类名对应类的构造器
函数式接口的抽象方法的形参列表,决定调用哪个构造器
数组引用
格式
数组类型[] :: new