lambda表达式详解
先看看例子,看看Lambda的厉害之处
简化创建线程
new Thread(()->{
System.out.println("running...");
}).start();
简化比较器及输出
List<String> list = Arrays.asList("java", "c++", "c","python");
Collections.sort(list,(a,b)->a.length()-b.length());
//遍历打印
list.forEach(System.out::println);
Lambda表达式特点:1.函数式编程、2.参数类型自动判断、3.代码量少,简洁。
Lambda表达式的应用场景:任何有函数式接口的地方。
那函数式接口是啥呢?
我们先看一个案例:根据学生不同属性查找学生,如数学分数大于80等,大家可以自己思考一下怎么实现,并且要有很好的扩展性,因为每学期学生的课都可能不同,有可能需要添加新的功能。
实现方法一:最普通的一个个方法实现,这个方法重复代码太多了。
方法二:用策略模式,写一个策略接口,让方法实现这个接口。
public interface StudentFilter {
boolean compare(Student student);
}
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<Student>();
list.add(new Student("zhangsan",14,67));
list.add(new Student("lisi",13,89));
list.add(new Student("wangwu",15,97));
list.add(new Student("maliu",12,63));
list.add(new Student("zhaoqi",17,75));
getByFilter(list,new AgeFilter());
getByFilter(list,new ScoreFilter());
}
public static void getByFilter(ArrayList<Student> students,StudentFilter filter){
ArrayList<Student> list = new ArrayList<>();
for(Student student:students){
if(filter.compare(student)){
list.add(student);
}
}
printStudent(list);
}
public static void printStudent(ArrayList<Student> students){
for(Student student:students){
System.out.println(student);
}
}
方法三:使用内部类,因为方法二没添加一个功能就要添加一个子类比较麻烦,我们直接使用内部类。
getByFilter(list, new StudentFilter() {
@Override
public boolean compare(Student student) {
return student.getAge()>14;
}
});
getByFilter(list, new StudentFilter() {
@Override
public boolean compare(Student student) {
return student.getScore()>75;
}
});
System.out.println("-------------------");
getByFilter(list, new StudentFilter() {
@Override
public boolean compare(Student student) {
return student.getName().length()>5;
}
});
方法四:方法三还是有点麻烦啊,那我们用lambda表达式
有没有超级强!!!!
getByFilter(list,(e)->e.getAge()>14 );
getByFilter(list, (e)->e.getScore()>75);
System.out.println("-------------------");
getByFilter(list, (e)->e.getName().length()>5);
大家理解函数式接口是什么了吧。
函数式接口是:有且只有一个方法的接口
lambda表达式的语法
LambdaParameters -> LambdaBody
args->expr或者(object … args)->{函数式接口抽象方法实现逻辑}
1、()参数的个数,根据函数式接口里面抽象的参数个数来决定,当参数只有一个的时候,()可以省略,但建议不要省略
2、当expr逻辑非常简单的时候,{}和return可以省略
表达式案例
()->{}
()->{System.out.println(1);}
()->System.out.println(1)
()->{return 100;}
()->100
()->null
//可以写类型,也可以不写
(int x)->{return x+1;}
(int x)->x+1
(x)->x+1
x->x+1
扩展资料
jdk自带的函数式接口
Supplier 代表一个输出
Consumer 代表一个输入
BiConsumer 代表两个输入
Function 代表一个输入,一个输出(一般输入和输出是不同类型的)
UnaryOperator 代表一个输入,一个输出(输入和输出是相同类型的)
BiFunction 代表两个输入,一个输出(一般输入和输出是不同类型的)
BinaryOperator 代表两个输入,一个输出(输入和输出是相同类型的)
用法:还是前面那个案例
方法五:这样都不用写策略接口了
//一个输入,一个输出
//第一个Student代表参数类型,第二个Boolean代表返回值类型
//其它的也是这样写
Function<Student,Boolean> f=(e)->e.getAge()>14;
getByFilter(list,f);
//调用方法
System.out.println(f.apply(new Student(30)));
为什么要有lambda表达式?
函数式编程将是一种趋势,他是一种思想。
方法的引用
他是lambda表达式的一种简化
1、实例方法引用(静态方法的引用类似)
lambda1
Supplier s=()->new Student().getAge();
方法的引用1
Supplier s=new Student()::getAge;
s.get();
lambda2
Consumer<Integer> c1=(age)->new Student().changeAge(age);
方法的引用2
Consumer<Integer> c2=new Student()::changeAge;
lambda3
Function<Student,Boolean> f=(e)->e.getBoolean();
方法的引用3
Function<Student,Boolean> f=new Student()::getBoolean
2、对象方法引用:抽象方法的第一个参数类型刚好是实例方法的类
型,抽象方法剩余的参数恰好可以当做实例方法的参数。如果函
数式接口的实现能由上面说的实例方法调用来实现的话,那么就
可以使用对象方法引用
lambda
Consumer<Student> f=(Student e)->new Student().getAge();
方法引用
Consumer<Student> f2=Student::getAge;
3、构造方法引用
一个参数的构造方法
Consumer<Integer> f2=Student::new;
经过上面例子懂了方法的引用了吧。