概述
参考:
1
2
什么是lambda表达式
-
lambda意为λ,表示是一个函数,而一个函数只有唯一的输入输出映射,因此引出lambda表达式的定义
-
Lambda是一个
唯一匿名方法
-
一个接口,如果只有一个显式声明的抽象方法,那么它就是一个函数式接口。一般用@FunctionalInterface标注出来(也可以不标)
-
因为该接口有一个抽象方法,在new的时候需要@Override这个抽象方法
格式
什么可以省略?
可推断的都可省略,因此尽可能使用泛型
方框中都可以省略
因为在调用这个方法的时候,public int add(int int ) return 都是唯一且确定且必须存在的,因此可以被唯一推断出来,所以可以省略,省略后为
(x,y) -> x+y;
因为只有一行语句,所以代码块{}可省,return可省
1.预定义的函数式接口
在JDK中定义了很多的函数式接口,例如BiFunction接口,就可以传入两个参数,返回一个参数,无需自定义;当然三个传参还是需要自定义的
1.1
函数型接口
1.JDK预定义了很多函数式接口以避免用户重复定义。最典型的是Function
:
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
这个接口代表一个函数,接受一个T类型的参数,并返回一个R类型的返回值。
消费型接口
2.另一个预定义函数式接口叫做Consumer
,跟Function的唯一不同是它没有返回值。
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
供给型接口
3.Supplier
有一个get()方法
@FunctionnallInterface
public interface Supplier<T>{
T get();
}
断定型接口
4.还有一个Predicate
断定,用来判断某项条件是否满足。经常用来进行筛滤操作:
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
1.2函数式接口的测试
public class LambdaTest {
public static void main(String[] args) {
//1.Runnale接口测试————run()
Runnable r = () -> System.out.println("测试");
r.run();
//2.Function接口测试————— T apply(X x)
Function<Integer, Integer> fun = (age) -> {
System.out.println("年龄为:" + age);//年龄为:21
return age + 1;
};
System.out.println("下次过生日的年龄:" + fun.apply(21));//下次过生日的年龄:22
//3.Consumer接口测试————accept(T t)
//3.1加泛型,推断s为String类型
Consumer<String> con = (s) -> System.out.println(s + "666666");//双击关注666666
con.accept("双击关注");
//3.2不加泛型需要指定,默认为Object
Consumer con2 = (s) -> System.out.println(s + "777777");//养猪厂子777777
con2.accept("养猪厂子");
//4.Supplier接口测试
//4.1不加泛型,则不推断
Supplier sup = () -> {
return new Integer(1);
};
//4.2加泛型,则可推断返回值为Integer
Supplier<Integer> sup2 = () -> 1;
//5.Predicate接口测试
Predicate<Integer> pred = (i) -> i > 10;
System.out.println(pred.test(11));//ture
System.out.println(pred.test(9));//false
}
}
2.自定义函数式接口
定义函数式接口,接收多个参数
@FunctionalInterface
public interface MyFunction<X,Y,Z,T> {
T fun(X x,Y y ,Z z);
}
使用
//6.自定义MyFunction接口
MyFunction<Integer,Integer,Integer,String> myFun =
(age,weight,higth) -> "年龄为:" + age
+ "体重为:" + weight
+ "身高为:" + higth;
String myInfo = myFun.fun(21, 145, 181);
System.out.println(myInfo);//年龄为:21体重为:145身高为:181
3.方法引用
- 当实现@FunctionalInterface的函数式接口使用lambda表达式时,
如果方法体直接调用 某个类or对象 的 静态or非静态方法,
且返回值和形参都高度相同or完全相同,那么就可以使用方法引用 编译看左
:类型的推断需要左边函数类的泛型来指定
3.1对象::非静态方法
Function fun = p :: myHight;即把fun中的唯一抽象函数apply() 和 myHight()方法绑定,调用fun.apply(1)相当于调用p.myHight(1)
public class LambdaTest2 {
public static void main(String[] args) {
//0. People的非静态方法myHight()的形参 和 Function类的apply()方法的形参对应
// 的返回值 和 的返回值对应
People p = new People(21,"张家豪");
//1.用 对象p :: 非静态方法
Function<Integer,String> fun = p :: myHight;
//2.此时的fun对象中的apply()方法已经和 p对象中的myHight()方法绑定
System.out.println(fun.apply(181));
}
}
class People{
int age;
String name;
public String myHight(Integer hight){
return "my hight is " + hight;
}}
3.2类 :: 静态方法
。。。。。。。。
//编译看左:左边需要指定泛型,才能推断出右边的参数类型
Consumer<Integer> con = People::describe;
con.accept(2);
}
}
class People {
int age;
String name;
public static void describe2(Integer i) {
System.out.println("People类有" + i + "个属性参数");
System.out.println("一个是name,一个是age");
}
3.3类 :: 实例方法
参考
4.构造器引用
和方法引用类似
构造器的形参 = 函数式接口的抽象方法
Function<String,People> fun1 = s -> new People(s);
People p1 = fun1.apply("张豪猪");
Function<String,People> fun2 = People::new;
People p2 = fun2.apply("豪猪张");
BiFunction<Integer,String,People> bifun1 = People::new;
People p3 = bifun1.apply(21, "豪张猪");
}
}
@AllConstructor
class People {
int age;
String name;
5.数组引用
数组引用算是构造器引用的一种,可以引用一个数组的构造
Function<Integer,People[]> fun1 = p -> new People[p];
People[] arr1 = fun1.apply(10);//创建一个长度为10的People数组
Function<Integer,People[]> fun2 = People[]::new;
fun2.apply(20);
}
}
class People {
int age;
String name;
区别与总结
1.类型推断
编译看左
有一个People的静态方法 public static void describe(Integer count) {。。}
则必须通过 Consumer <Integer> con = People::describe;
而不能 Consumer con = People::describe;
因为后者不能推断出con.accept()需要什么类型的参数
泛型顺序对应形参顺序
Function<x,y> fun = 是如何确定谁是形参谁是返回值的呢?
- 第一个是形参,第二个是返回值
而此时因为一一对应,Function<Integer,String>一定是Integer为形参,String为返回值
- 》》》当BiFunction<T, U, R> bifun= 时,R是返回值类型,T和U的顺序也已经固定
2.能省则省
凡是能唯一确定推断的都能省略
(s) ->{return 一个语句}
可写为s -> 一个语句
3.代码绑定
例如:
- Function<Integer,String> fun = p :: myHight就是把myHight()方法绑定给了fun.apply()
- Supplier sup = () -> {…return i } ; 则是把{…return i }代码块绑定给sup.get()
4.方法引用和lambda的联系
方法引用本质就是lambda表达式,只是在上一个例子中Supplier<Integer> sup = () -> {.....return i } ;
里面的{.....return i }
如果是被封装到了某一个特定的方法,那么可以直接使用方法引用,而不需要把代码块的内容挨个写出来
5.构造器引用和方法引用的联系
构造器引用本质是方法引用,方法体就是new 一个对象,并返回,因此形如:
但一定要有new
6.数组引用和构造引用的联系
之前的构造引用都是new一个对象,而数组引用是new一个数组,仅此而已,形如:
forEach的lambda表达式
参考
最后
以上就是直率发箍为你收集整理的lambda表达式和方法引用什么是lambda表达式格式1.预定义的函数式接口2.自定义函数式接口3.方法引用4.构造器引用5.数组引用区别与总结forEach的lambda表达式的全部内容,希望文章能够帮你解决lambda表达式和方法引用什么是lambda表达式格式1.预定义的函数式接口2.自定义函数式接口3.方法引用4.构造器引用5.数组引用区别与总结forEach的lambda表达式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复