1.什么是Lambda表达式?
“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。
2.为什么要用Lambda表达式?
个人理解:因为简洁,节省代码
3.Lambda表达式用法:
- 一、lambda表达式的基本语法:java8中引入了一个新的操作符“->”改操作符称为箭头操作符或lambda操作符
- 箭头操作符将lambda表达式拆分成两部分
- 左侧:lambda 表达式的参数列表
- 右侧:lambda 表达式中所学执行的功能,即lambda体
- 语法格式一:无参数,无返回值
()->System.out.println(“Hello Lambda!”);- 语法格式二:有一个参数,并且无返回值
(x)->System.out.println(“Hello Lambda!”);- 语法格式三:若只有一个参数,()可以省略不写
x->System.out.println(“Hello Lambda!”);- 语法格式四:有两个以上的参数,有返回值, 并且lambda体中有多条语句
- 语法格式五:若lambda体中只有一条语句,return和{}都可以省略不写
- 语法格式六:lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”
(x , y) -> Integer.compare(x, y);- 二:lambda表达式需要“函数式接口”的支持
- 函数式接口:接口只有一个抽象方法的接口,成为函数式接口可以使用注解@FunctionalInterface
4.Lambda表达式应用和对比
假设,我们现在有一个需求:获取当前公司中员工年龄大于35的员工信息
员工的信息:
List<Employee> employees = Arrays.asList(
new Employee("1", 18, 9999.99),
new Employee("2", 25, 6666.99),
new Employee("3", 12, 33333.99),
new Employee("4", 68, 3333.99),
new Employee("5", 8, 77777.99)
);
最一般的做法:写一个方法判断年龄,然后测试时传入员工信息
public List<Employee> filterEmployees(List<Employee> list){
List<Employee> emps =new ArrayList<>();
for(Employee emp: list) {
if (emp.getAge()>12) {
emps.add(emp);
}
}
return emps;
}
@Test
public void test3() {
List<Employee> list = filterEmployees(employees);
for(Employee employee :list) {
System.out.println(employee.getAge());
}
}
但是现在有心的需求,获取当前公司中员工工资大于5000的员工信息,这时候就需要再写一个方法来判断薪资
public List<Employee> filterEmployees2(List<Employee> list){
List<Employee> emps =new ArrayList<>();
for(Employee emp: list) {
if (emp.getSalary()>5000) {
emps.add(emp);
}
}
return emps;
}
缺点:如果再添加其他需求,还需要添加新的方法,这样就产生了大量冗余。
优化方法一:策略模式
创建一个接口供方法调用实现
public interface MyPredicate<T> {
public boolean test(T t);
}
用方法来实现接口
public List<Employee> filterEmployee(List<Employee> list, MyPredicate<Employee> mp){
List<Employee> employees= new ArrayList<>();
for(Employee employee :list) {
if (mp.test(employee) ) {
employees.add(employee);
}
}
return employees;
}
调用写好的方法
@Test
public void test4() {
List<Employee> list = filterEmployee(employees,new FilterEmployeeByAge());
for(Employee employee : list) {
System.out.println(employee.getAge());
}
}
缺点:当添加新的需求,则需要添加新的接口
优化方式二:匿名内部类
@Test
public void test05() {
List<Employee> list = filterEmployee(employees, new MyPredicate<Employee>() {
@Override
public boolean test(Employee t) {
return t.getSalary()<=5000;
}
});
for(Employee employee :list) {
System.out.println(employee);
}
}
优化方式三:Lambda表达式
@Test
public void test6() {
List<Employee> list = filterEmployee(employees, (e) -> e.getSalary()>=3000 );
list.forEach(System.out::println);
}
两句话就解决了的问题,很简洁有木有啊!
lambda表达式中传入的employees相当于方法一中MyPredicate接口传进的 t 变量, (e) -> e.getSalary()>=3000 就相当于MyPredicate接口的实现。