24 Lambda表达式
Lambda表达式
避免你匿名内部类定义过多
可以让你的代码看起来很简洁
去掉了一堆没有意义的代码,只留下核心的逻辑
lambad表达式
按顺序一步步简化,最后用lambda
lambad表达式的本质:作为函数式接口的实例
public class TestLambda {
//3.静态内部类
static class Like2 implements ILike{
@Override
public void lambda() {
System.out.println("i like lambda2");
}
}
public static void main(String[] args) {
//接口 实现类 相当于子类父类
ILike like = new Like();
like.lambda();
like = new Like2();
like.lambda();
//4.局部内部类
class Like3 implements ILike{
@Override
public void lambda() {
System.out.println("i like lambda3");
}
}
like = new Like3();
like.lambda();
//5.匿名内部类,没有类的名称,必须借助父类和接口
like = new Like(){
@Override
public void lambda() {
System.out.println("i like lambda4");
}
};
like.lambda();
//6.用lambda简化
like = () ->{
System.out.println("i like lambda5");
};
like.lambda();
}
}
//1.定义一个函数式接口
interface ILike{
void lambda();
}
//2.实现类
class Like implements ILike{
@Override
public void lambda() {
System.out.println("i like lambda");
}
}
总结:
lambda表达式只能有一行代码的情况下才能简化成为一行,如果有多行那么就用代码块包裹
前提是接口为就函数式接口
多个参数也可以去掉参数类型,要去掉都去掉,必须加上括号
public class TestLambda2 {
public static void main(String[] args) {
ILove love = null;
//lambda表示简化
//匿名内部类
/*ILove love = new Love(){
@Override
public void love(int a) {
System.out.println("i love" + "\t" +a);
}*/
/* ILove love = (int a) ->{
System.out.println("i love" + "\t" +a);
};
//简化1:参数类型
love = (a)->{
System.out.println("i love" + "\t" +a);
};*/
//简化2:简化括号
love = a -> {
System.out.println("i love" + "\t" +a);
};
//简化3:去掉花括号
love = a ->System.out.println("i love" + "\t" +a);
love.love(2);
}
interface ILove{
void love(int a);
}
class Love implements ILove{
@Override
public void love(int a) {
System.out.println("i love" + "\t" +a);
}
}
}
格式:
->:lambda操作符
左边:lambda形参列表(其实就是接口中的抽象方法的形参列表)
右边:lambda体 (其实就是重写的抽象方法的方法体)
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
int compare1 = com1.compare(12, 21);
Comparator<Integer> com2 = (o1,o2) -> Integer.compare(o1,o2);
int compare12 = com1.compare(12, 21);
}
总结:
左边: lambda形参列表的参数列表可以省略;如果lambda形参列表只有一个参数,其一对()也可省略。
右边:lambda体 应该使用一对{}包裹;如果只有一条执行语句(return 语句),可以省略{}和return关键字
方法引用
方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
方法引用的使用
-
使用情景:当要传递给lambda体的操作,已经有实现的方法了,可以使用方法引用。
-
方法引用,本质上就是lambda表达式,而lambda表达式作为函数式接口的实例。所以,方法引用,也是函数式接口的实例。
-
使用格式: 类(或对象):: 方法名
-
具体分为如下的三种情况:
情况1 对象 :: 非静态方法
情况2 类 :: 静态方法
情况3 类 :: 非静态方法
-
方法引用使用的要求:要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同(针对情况1 和 情况2)
//情况一:对象 :: 实例方法
//Consumer中的void accept(T t)
//PrintStream中的void print(T t)
Consumer<String> con1 = str -> System.out.println(str);
con1.accept("北京");
//方法引用
PrintStream ps = System.out;
Consumer<String> con2 = ps::println;
con2.accept("beijing");
//情形二: 类 :: 静态方法
//Comparator中的int compare(T t1,T t2)
//Integer中int compare(T t1,T t2)
Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2);
System.out.println(com1.compare(12,21));
//方法引用
Comparator<Integer> com2 = Integer::compare;
System.out.println(com2.compare(12,2));
//Function中的 R apply(T t)
//Math 中的Long round(Double d)
Function<Double,Long> func1 = d -> Math.round(d);
System.out.println(func1.apply(12.3));
//方法引用
Function<Double,Long> func2 = Math::round;
System.out.println(func2.apply(12.6));
//情形三: 类 :: 实例方法(有难度)
//Comparator中的 int compare(T t1,T t2)
//String 中的 int t1.compareTo(t2)
Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
System.out.println(com1.compare("abc", "abd"));
//方法引用
Comparator<String> com2 = String::compareTo;
System.out.println(com2.compare("abd","abm"));
//BiPredicate 中的 boolean test(T t1, T t2)
//String 中的 boolean t1.equals(t2)
BiPredicate<String,String> pre1 = (s1,s2) -> s1.equals(s2);
System.out.println(pre1.test("abc","abd"));
BiPredicate<String,String> pre2 = String::equals;
System.out.println(pre2.test("add","ass"));
构造器引用
和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致,抽象方法的返回值类型即为构造器所属的类的类型
//Supplier中的 T get()
//Person的空参构造器:Person() T就是Person的对象,下面都这样
Supplier<Person> sup = new Supplier<Person>() {
@Override
public Person get() {
return new Person();
}
};
System.out.println("==============");
Supplier<Person> sup1 = () -> new Person();
System.out.println(sup1.get());
System.out.println("================");
//构造器引用
Supplier<Person> sup2 = Person :: new;
System.out.println(sup2.get());
}
//Function中的 R apply(T t)
Function<Integer,Person> func1 = id -> new Person(id);
Person person = func1.apply(1001);
//构造器引用
Function<Integer,Person> func2 = Person :: new;
//BiFunction 中的 R apply(T t, U u)
BiFunction<Integer,String,Person> func3 = (id, name) -> new Person(id,name);
System.out.println(func3.apply(1001,"Tom"));
//构造器引用
BiFunction<Integer,String,Person> func4 = Person :: new;
数组引用
可以把数组看作是一个特殊的类,则写法与构造器一致
Function<Integer,String[]> func = new Function<Integer, String[]>() {
@Override
public String[] apply(Integer integer) {
return new String[integer];
}
};
//Function中的 R apply(T t)
Function<Integer,String[]> func1 = length -> new String[length];
//数组引用
Function<Integer,String[]> func2 = String[]::new;
String[] strings = func2.apply(10);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)