基本使用
lambda表达式简介
什么是lambda表达式
- lambda是java8添加的一个新特性,就是一个匿名函数
为什么使用lambda表达式
- 使用lambda可以对一个接口进行非常简洁的实现。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24public class Main {
public static void main(String[] args) {
//1. 使用接口实现类
Comparator comparator = new MyComperator();
//2. 使用匿名内部类
Comparator comparator1 = new Comparator() {
public int compare(int a, int b) {
return a-b;
}
};
//3.使用lambda表达式来实现接口
Comparator comparator2 = (a,b)->a-b;
}
}
class MyComperator implements Comparator{
public int compare(int a, int b) {
return 0;
}
}
interface Comparator{
int compare(int a,int b);
}
lambda对接口的要求
- 虽然可以用lambda表达是对某些接口进行简单实现,但是并不是所有接口都可以用lambda表达式来实现。要求接口中定义的必须要实现的抽象方法只能有一个。
在Java8对接口加了一个新的特性:default.lambda表达式要求要实现的方法只能有一个
@FunctionalInterface
- 修饰函数是接口(抽象方法只有一个),所以用lambda表达式的接口一般都加上此注解
lambda基础表达式
- lambda表达式是一个匿名函数,由参数列表和方法体构成
- ()用来描述参数列表
- {}用来描述方法体
- ->lambda运算符,读作goes to
1 | //无参无返回值 |
- lambda基础实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43//无参无返回
LambdaNoneReturnNoneParameter lambda1 = ()->{
System.out.println("hello world");
};
lambda1.test();//hello world
//无返回值,单个参数
LambdaNoneReturnSingleParameter lambda2 = (int a)->{
System.out.println(a);
};
lambda2.test(10);
//10
//无返回值,多个参数
LambdaNoneReturnMutipleParameter lambda3 = (int a,int b)->{
System.out.println(a+b);
};
lambda3.test(10,20);
//30
//无参数有返回值
LambdaSingleReturnNoneParameter lambda4=()->{
System.out.println("lambda4");
return 100;
};
System.out.println(lambda4.test());
//lambda4/n100
//有返回值,一个参数
LambdaSingleReturnSingleParameter lambda5 = (int a)->{
System.out.println("lambda5");
return a*3;
};
System.out.println(lambda5.test(4));
//lambda5/n12
//有返回值,多个参数
LambdaSingleReturnMutipleParameter lambda6 = (int a,int b)->{
System.out.println("lambda6");
return a+b;
};
System.out.println(lambda6.test(5,6));
//lambda6/n11
lambda语法精简
简化参数类型
- 由于在接口的抽象方法中已经定义了参数的数量和类型,所以在lambda表达式中,参数的类型可以忽略
- 备注: 如果需要省略类型,则每一个参数的类型都要省略
1
2
3
4
5LambdaNoneReturnMutipleParameter lambda1 = (a,b)->{
System.out.println(a+b);
};
lambda1.test(2,3);
//5
简化参数小括号
- 如果参数列表中,参数的数量只有一个,此时小括号可以省略
1
2
3
4
5LambdaNoneReturnSingleParameter lambda2 = a->{
System.out.println(a);
};
lambda2.test(5);
//5
简化方法大括号
- 如果此时方法体中只有一条语句,此时大括号可以省略
1
2
3LambdaNoneReturnSingleParameter lambda3 = a-> System.out.println(a);
lambda3.test(6);
//6
简化return
- 如果方法体中唯一的一条语句是一个返回语句,则省略大括号的同时也必须省略return
1
2
3
4
5
6
7LambdaSingleReturnNoneParameter lambda4 = ()->10;
System.out.println(lambda4.test());
//10
LambdaSingleReturnMutipleParameter lambda5 = (a,b)->a+b;
System.out.println(lambda5.test(5,4));
//9
语法进阶
## 方法引用
一般方法的引用
语法:方法的隶属者::方法名
注意:
- 1.参数数量和类型一定要和接口中定义的方法一致
- 2.返回值的类型一定要和接口中定义方法一致
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class Syntax3 {
private static int change(int a){
return a*2;
}
public static void main(String[] args) {
//定一个方法,相当于只有一个值的参数,相当于return change(a);
LambdaSingleReturnSingleParameter lambda1 = a->change(a);
//方法引用:引用了'类::方法名'的静态change方法的实现
LambdaSingleReturnSingleParameter lambda2 = Syntax3::change;
//引用对象的方法
Syntax3 syntax3 = new Syntax3();
LambdaSingleReturnSingleParameter lambda3 = syntax3::change2;
}
private int change2(int a){
return a*3;
}
}
构造方法的引用精简
1 | public class Person { |
1 | public class Syntax4 { |
- 构造方法的引用精简是依托于接口中参数,对应构造方法的参数
lambda操作集合列表
排序1
需求:一直再一个ArrayList中有若干个Person对象,将这些Person对象按照年龄进行降序排序
1
2
3
4
5
6
7
8
9
10
11
12ArrayList<Person> list = new ArrayList<>();
list.add(new Person("a", 17));
list.add(new Person("b", 12));
list.add(new Person("c", 3));
list.add(new Person("d", 144));
list.add(new Person("e", 15));
list.add(new Person("f", 18));
list.add(new Person("g", 1));
list.sort((o1, o2) ->
o2.age - o1.age
);
System.out.println(list);实现原理就是实现了sort中的Comparator接口的compare方法
排序2
使用TreeSet自带的排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//使用Lambda表达式来实现Comparetor接口,并实例化一个TreeSet对象
TreeSet<Person> set = new TreeSet<>((o1, o2) -> {
if (o1.age > o2.age) {
return -1;
} else {
return 1;
}
});
set.add(new Person("a", 17));
set.add(new Person("b", 12));
set.add(new Person("c", 3));
set.add(new Person("d", 144));
set.add(new Person("e", 15));
set.add(new Person("f", 18));
set.add(new Person("g", 1));
System.out.println(set);因为Tree会根据排序规则是否为0判断是否为统一元素去重,所以表达和上面有所不同
集合遍历
用list的forEach方法遍历,lambda实现一个Consumer1
2
3
4
5
6
7
8
9
10ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list,1,2,3,4,5,6,7);
//对所有输出
list.forEach(System.out::println);
//仅输出偶数
list.forEach(ele->{
if(ele%2==0){
System.out.println(ele);
}
});
删除集合元素
删除满足条件的集合元素,删除年龄为偶数的元素
1
2
3
4
5
6
7
8
9
10
11
12ArrayList<Person> list = new ArrayList<>();
list.add(new Person("a", 17));
list.add(new Person("b", 12));
list.add(new Person("c", 3));
list.add(new Person("d", 144));
list.add(new Person("e", 15));
list.add(new Person("f", 18));
list.add(new Person("g", 1));
//删除年龄为偶数的元素
list.removeIf(person -> person.age % 2 == 0);
System.out.println(list);是重写了removeIf的参数Predicate,lambda实现了他的test方法
操作线程
创建线程
- 匿名内部类通过实现Runnable接口创建线程
1
2
3
4
5
6Thread thread = new Thread(()->{
for (int i = 0; i <100 ; i++) {
System.out.println(i);
}
});
thread.start();
系统内置函数式接口
闭包
1 | public static void main(String[] args) { |
- 此时输出是10
- 问题:按说执行完getNumber了局部变量num就会销毁,怎么还能获取到值
- 闭包会提升变量的生命周期
- lambda中使用的局部变量一定是常量,如果没有写final,编译时候会自动加上final,不要修改lambda中调用的局部变量的值