Lambda表达式
1. 前序
1.1 需求1
-
假如说有这样一个需求,需要将一个list集合按照某种顺序排序。 -
一般的做法 -
public class TestMain {
@Test
public void test01(){
List<String> list = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return -Integer.compare(Integer.parseInt(o1),Integer.parseInt(o2));
}
});
System.out.println(list.toString());
}
}
-
使用lambda表达式 -
public class TestMain {
@Test
public void test01(){
List<String> list = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return -Integer.compare(Integer.parseInt(o1),Integer.parseInt(o2));
}
});
System.out.println(list.toString());
Comparator<String> comparator = (x,y) -> -Integer.compare(Integer.parseInt(x),Integer.parseInt(y));
Collections.sort(list,comparator);
System.out.println(list.toString());
}
}
1.2 需求2
-
假设有一个员工类 -
public class Employee {
public String name;
public Integer age;
public Double salary;
public Employee() {
}
public Employee(String name, Integer age, Double salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
1.2.1 选出员工年龄大于25岁的
-
@Test
public void test02(){
List<Employee> employees = Arrays.asList(
new Employee("张三", 30, 9999.99),
new Employee("李四", 20, 7777.77),
new Employee("王五", 10, 6666.66),
new Employee("陈六", 27, 4444.44),
new Employee("田七", 35, 3333.33)
);
List<Employee> list01 = filterEmployeeByAge(employees);
for (Employee employee:list01){
System.out.println(employee);
}
}
public List<Employee> filterEmployeeByAge(List<Employee> employees){
List<Employee> list = new ArrayList<>();
for (Employee employee:employees){
if (employee.getAge() > 25){
list.add(employee);
}
}
return list;
}
运行结果:
Employee{name='张三', age=30, salary=9999.99}
Employee{name='陈六', age=27, salary=4444.44}
Employee{name='田七', age=35, salary=3333.33}
1.2.2 选出 薪资大于 5000 的
-
@Test
public void test02(){
List<Employee> employees = Arrays.asList(
new Employee("张三", 30, 9999.99),
new Employee("李四", 20, 7777.77),
new Employee("王五", 10, 6666.66),
new Employee("陈六", 27, 4444.44),
new Employee("田七", 35, 3333.33)
);
List<Employee> list02 = filterEmployeeBySalary(employees);
for (Employee employee:list02){
System.out.println(employee);
}
}
public List<Employee> filterEmployeeBySalary(List<Employee> employees){
List<Employee> list = new ArrayList<>();
for (Employee employee:employees){
if (employee.getSalary() > 5000){
list.add(employee);
}
}
return list;
}
1.2.3 策略设计模式
-
发现这两个方法其实大致相同,只是一个是年龄,一个是薪资,可以进行改进 -
public interface MyPredicate<T> {
boolean test(T t);
}
-
public class FilterEmployeeByAge implements MyPredicate<Employee> {
@Override
public boolean test(Employee employee) {
return employee.getAge() > 25;
}
}
-
public class FilterEmployeeBySalary implements MyPredicate<Employee> {
@Override
public boolean test(Employee employee) {
return employee.getSalary() > 5000;
}
}
-
@Test
public void test03(){
List<Employee> employees = Arrays.asList(
new Employee("张三", 30, 9999.99),
new Employee("李四", 20, 7777.77),
new Employee("王五", 10, 6666.66),
new Employee("陈六", 27, 4444.44),
new Employee("田七", 35, 3333.33)
);
List<Employee> list = filterEmployee(employees, new FilterEmployeeByAge());
for (Employee employee : list){
System.out.println(employee);
}
System.out.println("=======================================");
List<Employee> list1 = filterEmployee(employees, new FilterEmployeeBySalary());
for (Employee employee : list1){
System.out.println(employee);
}
}
public List<Employee> filterEmployee(List<Employee> employees, MyPredicate<Employee> myPredicate){
List<Employee> list = new ArrayList<>();
for (Employee employee : employees){
if (myPredicate.test(employee)){
list.add(employee);
}
}
return list;
}
-
策略设计模式,定义一个统一的接口,根据不同的需求,有不同的实现,当需求变动时,只需要修改添加的实现类就可以了,
1.2.4 lambda表达式
-
上述的代码需要定义各种不同的实现类,其实看起来也是挺麻烦的,接下来用lambda实现 -
public interface MyPredicate<T> {
boolean test(T t);
}
-
@Test
public void test04(){
List<Employee> employees = Arrays.asList(
new Employee("张三", 30, 9999.99),
new Employee("李四", 20, 7777.77),
new Employee("王五", 10, 6666.66),
new Employee("陈六", 27, 4444.44),
new Employee("田七", 35, 3333.33)
);
List<Employee> list = filterEmployee(employees, e -> e.getAge() > 25);
for (Employee employee : list){
System.out.println(employee);
}
System.out.println("=======================================");
List<Employee> list1 = filterEmployee(employees, e -> e.getSalary() > 5000);
for (Employee employee : list1){
System.out.println(employee);
}
}
public List<Employee> filterEmployee(List<Employee> employees, MyPredicate<Employee> myPredicate){
List<Employee> list = new ArrayList<>();
for (Employee employee : employees){
if (myPredicate.test(employee)){
list.add(employee);
}
}
return list;
}
-
这里依然使用了 filterEmployee 方法,不过传入的方式改用了 lambda 方式 -
也就是说 e -> e.getAge() > 25 就相当于 filterEmployeeByAge 类,e -> e.getSalary() > 5000 就相当于 filterEmployeeBySalary 类
1.2.5 Stream+lambda
-
上面的代码还可以结合Stream流进行改进 -
@Test
public void test05(){
List<Employee> employees = Arrays.asList(
new Employee("张三", 30, 9999.99),
new Employee("李四", 20, 7777.77),
new Employee("王五", 10, 6666.66),
new Employee("陈六", 27, 4444.44),
new Employee("田七", 35, 3333.33)
);
employees.stream()
.filter(e -> e.getAge() > 25)
.forEach(System.out::println);
}
-
是不是感觉有点不像java代码了,噗哈哈哈!好了,现在开始进入正题
2. lambda表达式
2.1 基础语法
2.2 内置函数式接口
-
需要注意的是,lambda实现的接口,你会发现这些接口中只有一个方法,如果接口中有多个方法,lambda表达式无法判断要实现哪个方法,所以,lambda表达式的使用场景只适用于函数式接口中。接口中只有一个方法的接口叫函数式接口。 -
另外,有人会问了,难道每次使用lambda表达式时,都需要自己先定义一个函数式接口么? -
答案是不用的,java中内置了四个核心的函数式接口, -
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
-
@FunctionalInterface
public interface Supplier<T> {
T get();
}
-
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
-
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
-
使用的时候,可以直接把这几个接口当参数传入,用lambda表达式实现其方法就可以了。
睡觉了,有空再补完剩下的。
|