lamdda表达式
介绍说明
lambda表达式作用
- 可以替代只有一个抽象函数的接口实现,告别匿名内部类,代码看起来更简洁易懂。
- 同时还提升了对集合、框架的迭代、遍历、过滤数据的操作。
- 可以极大的减少代码冗余,同时代码的可读性要好过冗长的内部类,匿名类。
使用情景
1、需要自定义简单的代码块,不想写单独的方法调用。
2、日志输入不输入实现类信息,通过函数接口封装父类可以隐藏子类的实现过程,不会暴露把具体实现暴露在日志系统中。
3、可以作物业务前后的补充,先定义实现然后根据需求回调业务。
如何看懂别人的lambda表达式
当代码中出现"->"、"::"第一反应就是他用lambda表达式。
定义
A a=b->b++;
b就是我们出入参数,可以使用(b)、(int b)、b。
b++ 就是我们业务代码块,自定义的实现方式,相当于一个方法的内容实现。可以是{b++;};、b++。
A a=B::get;
get是B类中的一个方法。
B可以是类也可以是对象。
调用
这里才代码块的真正调用。
a.put©;
a是类A的别名,可能有疑问不用管他就这么定义。
put是A类的唯一抽象方法。
c标识我们出入代码的参数,就像方法的传参。
代码演示
1清楚函数式编程
进行函数式编程我们必须要先定义函数式接口,函数式接口使用 @FunctionalInterface 注解,提供一个唯一的抽象方法。
//之前函数式编程就已经出现的方式,是不是很熟悉,只不过我们之前用的比较少,在线程和异步的时候使用。
Runnable runnable = new Runnable(){
@Override
public void run() {
System.out.println("我最帅");
}
};
runnable.run();
2 lambda 表达式基础写法
lambda 表达式格式
函数接口 名称= (传参){接收参数,业务逻辑};
Runnable r1 = ()->{System.out.println("你第二帅");};
Runnable r2 = ()->System.out.println("你第二帅1");
//调用接口函数
r1.run();
r2.run();
3自定义函数接口
我使用的例子是有参数有返回值的函数接口方法
1、如果有多个参数,自己会匹配参数类型,不用定义参数类型
2、(参数){使用参数} 在{}中使用传递的参数进行业务逻辑的处理
3、如果没有定义返回值类型,就算我们在{return} 也是接收不到返回的数据。
LambdaInterface la = new LambdaInterface(){
@Override
public String get(Integer i) {
return "自定义函数返回";
}
};
System.out.println(la.get(1));
LambdaInterface la1 = (i)->{return i+"返回数据" ;};
LambdaInterface la2 = (i)->{return "单独返回数据" ;};
LambdaInterface la3 = (i)->{
i=i*100; //传入的参数做业务处理
return i+"业务处理,返回数据" ;
};
LambdaInterface la4 = (i)->"固定返回数据";
LambdaInterface la5 = (Integer i)->{return i+"带传参的数据类型,返回数据" ;};
LambdaInterface la6 = i->{return i+"不用()定义传参,返回数据" ;};
System.out.println(la1.get(100));
LambdaInterface自定义函数接口
@FunctionalInterface
public interface LambdaInterface {
public String get(Integer i);
}
4更简洁的::写法
方法引用 比(){} 更简洁的方式
类的实例或者类名::方法名;
LambdaInterface laa = a->LambdaA.get(a);
LambdaInterface laa1 = LambdaA::get;
System.out.println(laa.get(1));
System.out.println(laa1.get(1));
LambdaA类的测试方法
public class LambdaA {
public static String get(String a){
return "LambdaA 的get";
};
public static String get(Integer integer) {
return "LambdaA 的get integer"+integer;
};
public static String get1() {
return "LambdaA 的无参get";
};
public static void in(Integer i) {
i++;
};
public static void inDouble(String s, Integer integer) {
};
public static Integer inGet(String s) {
return 1;
};
public static String inUGet(String s) {
return "UnaryOperator";
}
public static Integer inDoubleget(String s, String s1) {
return 1;
}
public static String inDoubleOGet(String s, String s1) {
return "";
}
public String get() {
return "";
}
public static String getT() {
return "";
}
public LambdaA() {
}
public LambdaA(String a){
}
}
5java自定义的标准函数接口
java 提供几个标准函数接口 就不用我们自己定义函数接口了
Supplier 代表一个输出
Consumer 代表一个输入
BiConsumer 代表两个输入
Function 代表一个输入,一个输出(一般输入和输出是不同类型的)
UnaryOperator 代表一个输入,一个输出(输入和输出是相同类型的)
BiFunction 代表两个输入,一个输出(一般输入和输出是不同类型的)
BinaryOperator 代表两个输入,一个输出(输入和输出是相同类型的)
输入的参数需要指定泛型,否则出输入的参数应该Object。
Supplier s1 =LambdaA::get1;
System.out.println(s1.get());
Consumer<Integer> c1 = LambdaA::in;
int i = 0;
c1.accept(i);
System.out.println(i);
BiConsumer<String,Integer> b1 = LambdaA::inDouble;
b1.accept("",1);
Function<String,Integer> f1 = LambdaA::inGet ;
f1.apply("1");
UnaryOperator<String> u1 = LambdaA::inUGet;
u1.apply("1");
BiFunction<String,String,Integer> bf1 = LambdaA::inDoubleget;
bf1.apply("1","2");
BinaryOperator<String> bo1 = LambdaA::inDoubleOGet;
bo1.apply("2","1");
6方法引用的分类
静态方法引用 类名::staticMethod (args) -> 类名.staticMethod(args)
实例方法引用 inst::instMethod (args) -> inst.instMethod(args)
对象方法引用 类名::instMethod (inst,args) ->类名.instMethod(args)
构造方法引用 类名::new (args) -> new 类名(args)
//静态方法引用
Supplier s2 =LambdaA::get1;
//实例方法引用
LambdaA lA = new LambdaA();
Supplier<String> s3 =lA::get;
//对象方法引用 自动调用无参构造方法生成对象
Supplier<String> s4 =LambdaA::getT;
//构造方法引用
Consumer<String> s5 = LambdaA::new;
s5.accept("");
代码地址
https://gitee.com/zhang798/javaDemo.git
分支 java_lambda
git clone https://gitee.com/zhang798/javaDemo.git -b java_lambda