Lambda表达式的本质只是一个"语法糖",由编译器推断并帮你转换包装为常规的代码,因此你可以使用更少的代码来实现同样的功能,Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递),可以写出更简洁、更灵活的代码。
Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。 Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。
替代匿名内部类毫无疑问,lambda表达式用得最多的场合就是替代匿名内部类
实例1:实现Runnable方式创建线程
@Test
public void test4() throws Exception {
//使用匿名内部类:
new Thread(new Runnable() {
public void run() {
System.out.println(Thread.currentThread().getName());
}
}).start();
//用Lambda表达式
new Thread(() -> System.out.println(Thread.currentThread().getName())).start();
Thread.currentThread().join();
}
以上两种实现方式的代码执行效果完全一样,但是Lambda表达式却更加简洁,使得原本很多代码的写法变得更加洁、 优雅。
实例2:使用Comparator比较两个数字的大小
@Test
public void test3() {
//匿名内部类
Comparator comparator1 = new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
};
//lambda
Comparator comparator2 = (o1, o2) -> o1.compareTo(o2);
}
使用lambda表达式对集合进行迭代
Java的集合类是日常开发中经常用到的,甚至说没有哪个java代码中没有使用到集合类。。。而对集合类最常见的操作就是进行迭代遍历了。请看对比:
@Test
public void iterTest() {
List languages = Arrays.asList("java","scala","python");
//before java8
for(String each:languages) {
System.out.println(each);
}
//after java8
languages.forEach(x -> System.out.println(x));
languages.forEach(System.out::println);
}
Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使java的语言表达能力得到提升。
在软件工程中,一个众所周知的问题就是,不管你做什么,用户的需求肯定会变。比方说对于员工信息进行查询
那么首先创建一个员工Employee类。
package com.dongguo.java8.employee;
/**
* @author Dongguo
* @date 2021/8/14 0014-15:00
* @description:
*/
public class Employee {
private String name;
private int age;
private long salary;
public Employee() {
}
public Employee(String name, int age, long salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public long getSalary() {
return salary;
}
public void setSalary(long salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
需求1:获得当前公司员工年龄大于35的员工信息
package com.dongguo.java8.lambda;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Dongguo
* @date 2021/8/14 0014-15:02
* @description:
*/
public class EmployeeDemo {
//创建一个员工集合
List employees = Arrays.asList(new Employee("张三", 18, 3000),
new Employee("张三", 18, 4000),
new Employee("李四", 28, 5000),
new Employee("王五", 38, 6000),
new Employee("赵六", 48, 5500),
new Employee("田七", 58, 4500));
@Test
public void test1() {
List list = filterEmployeeByAge(employees);
System.out.println(list);
}
/**
* @author Dongguo
* @date 2021/8/14 0014 15:15
* @description:获得当前公司员工年龄大于35的员工信息
*/
public static List filterEmployeeByAge(List list) {
List emps = new ArrayList();
for (Employee emp : list) {
if (emp.getAge() > 35) {
emps.add(emp);
}
}
return emps;
}
}
运行结果:
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}, Employee{name='田七', age=58, salary=4500}]
需求更改
需求2:获取当前公司员工工资大于5000的员工信息
package com.dongguo.java8.lambda;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Dongguo
* @date 2021/8/14 0014-15:02
* @description:
*/
public class EmployeeDemo {
//创建一个员工集合
List employees = Arrays.asList(new Employee("张三", 18, 3000),
new Employee("张三", 18, 4000),
new Employee("李四", 28, 5000),
new Employee("王五", 38, 6000),
new Employee("赵六", 48, 5500),
new Employee("田七", 58, 4500));
@Test
public void test2() {
List list = filterEmployeeByAge(employees);
System.out.println(list);
}
/**
* @author Dongguo
* @date 2021/8/14 0014 15:19
* @description:需求:获取当前公司员工工资大于5000的员工信息
*/
public static List filterEmployeeBySalary(List list) {
List emps = new ArrayList();
for (Employee emp : list) {
if (emp.getSalary() > 5000) {
emps.add(emp);
}
}
return emps;
}
}
运行结果:
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}, Employee{name='田七', age=58, salary=4500}]
这是最容易 想到的方法,很显然根据不同条件获取信息,产生了过多的冗余代码,现在我们想办法对代码进行优化
优化1:
提取一个接口 ,提供一个公共方法
子类通过重写方法实现自己的判断
只需要通过一个方法就可以判断不同条件的过滤 ---采用策略模式
首先创建一个接口
package com.dongguo.java8.employee;
/**
* @author Dongguo
* @date 2021/8/14 0014-15:21
* @description:
*/
public interface MyPredicate {
public boolean predicate(T t);
}
创建两个实现类
package com.dongguo.java8.employee;
/**
* @author Dongguo
* @date 2021/8/14 0014-15:29
* @description:
*/
public class FilterEmployeeByAge implements MyPredicate {
@Override
public boolean predicate(Employee e) {
return e.getAge() > 35;
}
}
package com.dongguo.java8.employee;
/**
* @author Dongguo
* @date 2021/8/14 0014-15:30
* @description:
*/
public class FilterEmployeeBySalary implements MyPredicate {
@Override
public boolean predicate(Employee employee) {
return employee.getSalary() > 5000;
}
}
package com.dongguo.java8.lambda;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Dongguo
* @date 2021/8/14 0014-15:02
* @description:
*/
public class EmployeeDemo {
//创建一个员工集合
List employees = Arrays.asList(new Employee("张三", 18, 3000),
new Employee("张三", 18, 4000),
new Employee("李四", 28, 5000),
new Employee("王五", 38, 6000),
new Employee("赵六", 48, 5500),
new Employee("田七", 58, 4500));
@Test
public void test3() {
//获得当前公司员工年龄大于35的员工信息
List list = filterEmployee(employees,new FilterEmployeeByAge());
System.out.println(list);
//获取当前公司员工工资大于5000的员工信息
List list2 = filterEmployee(employees,new FilterEmployeeBySalary());
System.out.println(list2);
}
/**
* @author Dongguo
* @date 2021/8/14 0014 15:33
* @description:根据不同的条件过滤
*/
public static List filterEmployee( List list ,MyPredicate p){
List emps = new ArrayList();
for (Employee emp:list) {
if (p.predicate(emp)){
emps.add(emp);
}
}
return emps;
}
}
运行结果:
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}, Employee{name='田七', age=58, salary=4500}]
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}]
对代码优化最好的方式就是设计模式,现在有一个通用的过滤方法,如果再有其他过滤条件只需要添加一个实现MyPredicate接口的实现类就可以了,之前的代码都不需要修改,但是每添加一个过滤条件就要新创建一个实现类,也是非常麻烦的。
优化二:只通过提供的接口 使用匿名内部类自己去实现具体的判断
package com.dongguo.java8.lambda;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Dongguo
* @date 2021/8/14 0014-15:02
* @description:
*/
public class EmployeeDemo {
//创建一个员工集合
List employees = Arrays.asList(new Employee("张三", 18, 3000),
new Employee("张三", 18, 4000),
new Employee("李四", 28, 5000),
new Employee("王五", 38, 6000),
new Employee("赵六", 48, 5500),
new Employee("田七", 58, 4500));
/**
* @author Dongguo
* @date 2021/8/14 0014 15:33
* @description:根据不同的条件过滤
*/
public static List filterEmployee( List list ,MyPredicate p){
List emps = new ArrayList();
for (Employee emp:list) {
if (p.predicate(emp)){
emps.add(emp);
}
}
return emps;
}
@Test
public void test4() {
//获得当前公司员工年龄大于35的员工信息
List list = filterEmployee(employees, new MyPredicate() {
@Override
public boolean predicate(Employee employee) {
return employee.getAge() > 35;
}
});
System.out.println(list);
//获取当前公司员工工资大于5000的员工信息
List list2 = filterEmployee(employees, new MyPredicate() {
@Override
public boolean predicate(Employee employee) {
return employee.getSalary()>5000;
}
});
System.out.println(list2);
}
}
运行结果:
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}, Employee{name='田七', age=58, salary=4500}]
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}]
使用匿名内部类同样能够实现,但是在之前就说过lambda表达式可以替代匿名内部类
优化三:lambda表达式
package com.dongguo.java8.lambda;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Dongguo
* @date 2021/8/15 0015-15:33
* @description:
*/
public class TestLambda {
List employees = Arrays.asList(new Employee("张三", 18, 3000),
new Employee("张三", 18, 4000),
new Employee("李四", 28, 5000),
new Employee("王五", 38, 6000),
new Employee("赵六", 48, 5500),
new Employee("田七", 58, 4500));
@Test
public void test1() {
//获得当前公司员工年龄大于35的员工信息
List list = filterEmployee(employees, (employee) -> employee.getAge() > 35);
System.out.println(list);
//获取当前公司员工工资大于5000的员工信息
List list2 = filterEmployee(employees, (employee) -> employee.getSalary() > 5000);
System.out.println(list2);
}
/**
* @author Dongguo
* @date 2021/8/14 0014 15:33
* @description:根据不同的条件过滤
*/
public static List filterEmployee(List list, MyPredicate p) {
List emps = new ArrayList();
for (Employee emp : list) {
if (p.predicate(emp)) {
emps.add(emp);
}
}
return emps;
}
}
运行结果
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}, Employee{name='田七', age=58, salary=4500}]
[Employee{name='王五', age=38, salary=6000}, Employee{name='赵六', age=48, salary=5500}]
这样成功的从匿名内部类到Lambda表达式的使用
优化四:Stream API
Stream是对集合的包装,通常和lambda一起使用。让我们看下是如何使用
package com.dongguo.java8.lambda;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author Dongguo
* @date 2021/8/15 0015-15:33
* @description:
*/
public class TestLambda {
List employees = Arrays.asList(new Employee("张三", 18, 3000),
new Employee("张三", 18, 4000),
new Employee("李四", 28, 5000),
new Employee("王五", 38, 6000),
new Employee("赵六", 48, 5500),
new Employee("田七", 58, 4500));
@Test
public void test2() {
//获得当前公司员工年龄大于35的员工信息
employees.stream().filter(employee -> (employee.getAge() > 35)).forEach(System.out::println);
System.out.println("-------------------------------------");
//获取当前公司员工工资大于5000的员工信息
employees.stream().filter(employee -> (employee.getSalary() > 5000)).forEach(System.out::println);
}
}
运行结果:
Employee{name='王五', age=38, salary=6000}
Employee{name='赵六', age=48, salary=5500}
Employee{name='田七', age=58, salary=4500}
-------------------------------------
Employee{name='王五', age=38, salary=6000}
Employee{name='赵六', age=48, salary=5500}
这样最终我们的代码可以完成如此的精简,真是美好的体验。