Lambda表达式

Lambda表达式总结
使用范例以及例子
Lambda表达式基础语法
函数式接口
Lambda练习
Java8四大内置函数式接口
方法引用和构造器引用
使用范例以及例子
使用匿名内部类:

Comparatorcom = new Comparator() {
@Override
public int compare(Integer o1, Integer o2) { //降序排列
return Integer.compare(o2,o1);
}
};
1
2
3
4
5
6
使用Lambda表达式:

Comparator com = (x, y) -> Integer.compare(y, x);
1
下面给出一个例子来引入Lambda表达式。

给出一个Employee类,有name、age、salary三个属性:

public class Employee {
private String name;
private int age;
private double salary;

public Employee() {
}
public Employee(String name, int age, double salary) {
    this.name = name;
    this.age = age;
    this.salary = salary;
}
public String getName() {
    return name;
}
public int getAge() {
    return age;
}
public double getSalary() {
    return salary;
}

@Override
public String toString() {
    return "name='" + name + '\'' +
            ", age=" + age +
            ", salary=" + salary;
}

}

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
然后我们需要通过限制查询数据:

比如查询年龄>25岁的所有员工的信息;
再如查询工资>4000的员工信息;
首先给出一个List集合类模拟数据库表:

//将数组转换成集合的
List employees = Arrays.asList(
new Employee(“张三”,23,3333.33),
new Employee(“李四”,24,4444.44),
new Employee(“王五”,25,5555.55),
new Employee(“赵六”,26,6666.66),
new Employee(“田七”,27,7777.77)
);
1
2
3
4
5
6
7
8
原始方法
然后我们写分别查询出年龄大于25岁的员工信息和工资大于4000的员工信息,发现findEmployeesByAge和findEmployeesBySalary两个方法代码非常的相似,只有查询条件不同,所以这个方法是不太可取的。

public void test3(){
//年龄
List list = findEmployeesByAge(employees);
for(Employee emp : list){
System.out.println(emp);
}
//工资
System.out.println("---------------------");
List list2 = findEmployeesBySalary(employees);
for(Employee emp : list2){
System.out.println(emp);
}
}

//原始方法 : 查询出年龄大于25岁的(这个是最原始的方法)
public List findEmployeesByAge(Listlist){
Listemps = new ArrayList<>();
for(Employee emp : list){
if(emp.getAge() > 25){
emps.add(emp);
}
}
return emps;
}

//原始方法 : 查询出工资大于4000的(这个是最原始的方法)
//和上面的方法唯一的差别只有年龄和工资的改动,代码冗余
public List findEmployeesBySalary(Listlist){
Listemps = new ArrayList<>();
for(Employee emp : list){
if(emp.getSalary() > 4000){
emps.add(emp);
}
}
return emps;
}

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
优化方式一-使用策略模式来优化
策略模式需要行为算法族,于是我们创建查询行为的接口MyPredicate:

public interface MyPredicate {
public boolean test(T t);
}
1
2
3
并创建相关的实现类代表不同的算法行为: (分别是年龄> 25和工资> 4000的 ):

public class FilterEmployeeByAge implements MyPredicate {
@Override
public boolean test(Employee employee) {
return employee.getAge() > 25;
}
}
1
2
3
4
5
6
public class FilterEmployeeBySalary implements MyPredicate{
@Override
public boolean test(Employee employee) {
return employee.getSalary() >= 4000;
}
}
1
2
3
4
5
6
这时我们可以只需要创建通用的方法: 具体的调用只需要传入具体的实现类(接口作为参数)

public List filterEmployees(Listlist,MyPredicatemp){
Listemps = new ArrayList<>();
for(Employee emp : list){
if(mp.test(emp)){ //调用相应的过滤器
emps.add(emp);
}
}
return emps;
}
1
2
3
4
5
6
7
8
9
测试的时候就传入两个不同的类,来指定查询的行为

//优化方式一 : 使用策略设计模式进行优化 下面的方法只要写一个
public void test4(){
List list = filterEmployees(this.employees, new FilterEmployeeByAge());
for(Employee emp : list){
System.out.println(emp);
}
System.out.println("------------------------");
List list2 = filterEmployees(this.employees, new FilterEmployeeBySalary());
for(Employee emp : list2){
System.out.println(emp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
优化方式二-使用匿名内部类优化
这样的好处在于不需要创建接口的具体的实现类,(但是还是需要MyPredicate接口和filterEmployees()方法):

//优化方式二 : 使用匿名内部类 这样的好处是不要创建一个额外的 策略类
public void test5(){
List list = filterEmployees(this.employees, new MyPredicate() {
@Override
public boolean test(Employee employee) {
return employee.getSalary() > 4000;
}
});
for (Employee emp:list) {
System.out.println(emp);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
优化方式三-使用Lambda表达式
省去匿名内部类的没用的代码,增强可读性:(注意还是需要那个filterEmployees方法)

public void test6(){
List list = filterEmployees(this.employees, (e) -> e.getSalary() > 4000);
list.forEach(System.out::println);
}
1
2
3
4
优化方式四-使用Stream-API
使用StreamAPI完全不需要其他的代码,包括不需要filterEmployees()方法,代码很简洁:

public void test7(){
employees.stream().filter( (e) -> e.getSalary() < 4000 ).limit(2).forEach(System.out::println);
System.out.println("------------------");
employees.stream().map(Employee::getName).forEach(System.out::println); //打印所有的名字
}
1
2
3
4
5
Lambda表达式基础语法
关于箭头操作符:

Java8中引入了一个新的操作符,"->",该操作符称为箭头操作符或者Lambda操作符,箭头操作符将Lambda表达式拆分成两部分;
左侧: Lambda表达式的参数列表,对应的是接口中抽象方法的参数列表;
右侧: Lambda表达式中所需要执行的功能(Lambda体),对应的是对抽象方法的实现;(函数式接口(只能有一个抽象方法))
Lambda表达式的实质是 对接口的实现;
语法格式:

(一) 接口中的抽象方法 : 无参数,无返回值;
例如: Runnable接口中的run方法:

public void test1(){
/*final */int num = 2; //jdk1.7之前必须定义为final的下面的匿名内部类中才能访问

    Runnable r = new Runnable() {
        @Override
        public void run() {
            System.out.println("Hello world!" + num); //本质还是不能对num操作(只是jdk自己为我们设置成了final的)
        }
    };
    r.run();

    System.out.println("----------使用Lambda输出-----------");

    Runnable r1 = () -> System.out.println("Hello world!" + num);
    r1.run();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(二) 接口中的抽象方法 : 一个参数且无返回值; (若只有一个参数,那么小括号可以省略不写)
public void test2(){
// Consumercon = (x) -> System.out.println(x);
Consumercon = x -> System.out.println(x);
con.accept(“Lambda牛逼!”);
}
1
2
3
4
5
(三) 两个参数,有返回值,并且有多条语句 : 要用大括号括起来,而且要写上return
public void test3(){
Comparatorcom = (x,y) -> {
System.out.println(“函数式接口”);
return Integer.compare(y,x); //降序
};

 Integer[] nums = {4,2,8,1,5};
 Arrays.sort(nums,com);
 System.out.println(Arrays.toString(nums));

}
1
2
3
4
5
6
7
8
9
10
输出:

函数式接口
函数式接口
函数式接口
函数式接口
函数式接口
函数式接口
函数式接口
函数式接口
函数式接口
[8, 5, 4, 2, 1]
1
2
3
4
5
6
7
8
9
10
(四) 两个参数,有返回值,但是只有一条语句: 大括号省略,return省略
public void test4(){
Comparatorcom = (x,y) -> Integer.compare(x,y);//升序
Integer[] nums = {4,2,8,1,5};
Arrays.sort(nums,com);
System.out.println(Arrays.toString(nums));
}
1
2
3
4
5
6
输出:

[1, 2, 4, 5, 8]
1
(五) Lambda表达式的参数列表的数据类型 可以省略不写,因为JVM编译器通过上下文推断出数据类型,即"类型推断", (Integer x,Integer y ) -> Integer.compare(x,y)可以简写成(x,y) -> Integer.compare(x,y);
上联: 左右遇一括号省
下联: 左侧推断类型省
横批: 能省则省
1
2
3
函数式接口
若接口中只有一个抽象方法的接口称为函数式接口;
可以使用注解@FunctionlInterface来标识,可以检查是否是函数式接口;
例子: 对一个进行±*/的运算:

函数式接口:

@FunctionalInterface //函数式接口
public interface MyFunction {
public Integer getValue(Integer num);
}
1
2
3
4
通用函数:

public Integer operation(Integer num,MyFunction mf){
return mf.getValue(num);
}
1
2
3
测试:

public void test5(){
Integer res = operation(200, (x) -> x * x);
System.out.println(res);
}

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值