案例一
需求
调用Collections.sort()方法,通过定制排序比较两个Employee(先比较年龄,年龄相同按姓名比较),使用Lambda表达式作为参数传递。
实现
这里,我们先创建一个Employee类,为了满足需求,我们在Employee类中定义了姓名、年龄和工资三个字段,如下所示。
@Data @Builder @ToString @NoArgsConstructor @AllArgsConstructor public class Employee implements Serializable { private static final long serialVersionUID = -9079722457749166858L; private String name; private Integer age; private Double salary; }
接下来,我们在TestLambda类中定义一个成员变量employees,employees变量是一个List集合,存储了Employee的一个列表,如下所示。
protected List<Employee> employees = Arrays.asList( new Employee("张三", 18, 9999.99), new Employee("李四", 38, 5555.55), new Employee("王五", 60, 6666.66), new Employee("赵六", 8, 7777.77), new Employee("田七", 58, 3333.33) );
前期的准备工作完成了,接下来,我们就可以实现具体的业务逻辑了。
@Test public void test1(){ Collections.sort(employees, (e1, e2) -> { if(e1.getAge() == e2.getAge()){ return e1.getName().compareTo(e2.getName()); } return Integer.compare(e1.getAge(), e2.getAge()); }); employees.stream().forEach(System.out::println); }
上述代码比较简单,我就不赘述具体逻辑了。运行test1方法,得出的结果信息如下所示。
Employee(name=赵六, age=8, salary=7777.77) Employee(name=张三, age=18, salary=9999.99) Employee(name=李四, age=38, salary=5555.55) Employee(name=田七, age=58, salary=3333.33) Employee(name=王五, age=60, salary=6666.66)
如果想倒叙输出如何处理呢,只需要在将return Integer.compare(e1.getAge(), e2.getAge());
修改成-return Integer.compare(e1.getAge(), e2.getAge());
即可,如下所示。
@Test public void test1(){ Collections.sort(employees, (e1, e2) -> { if(e1.getAge() == e2.getAge()){ return e1.getName().compareTo(e2.getName()); } return -Integer.compare(e1.getAge(), e2.getAge()); }); employees.stream().forEach(System.out::println); }
再次运行test1方法,得出的结果信息如下所示。
Employee(name=王五, age=60, salary=6666.66) Employee(name=田七, age=58, salary=3333.33) Employee(name=李四, age=38, salary=5555.55) Employee(name=张三, age=18, salary=9999.99) Employee(name=赵六, age=8, salary=7777.77)
结果符合我们的需求。
案例二
需求
1.声明函数式接口,接口中声明抽象方法public String getValue(String str);
2.声明类TestLambda,类中编写方法使用接口作为参数,将一个字符串转换为大写,并作为方法的返回值。
3.再将一个字符串的第2个和第4个索引位置进行截取子串。
实现
首先,创建一个函数式接口MyFunction,在MyFunction接口上加上注解@FunctionalInterface标识接口是一个函数式接口。如下所示。
@FunctionalInterface public interface MyFunction { public String getValue(String str); }
在TestLambda类中声明stringHandler方法,参数分别为待处理的字符串和函数式接口的实例,方法中的逻辑就是调用函数式接口的方法来处理字符串,如下所示。
public String stringHandler(String str, MyFunction myFunction){ return myFunction.getValue(str); }
接下来,我们实现将一个字符串转换为大写的逻辑,如下所示。
@Test public void test2(){ String value = stringHandler("binghe", (s) -> s.toUpperCase()); System.out.println(value); }
运行test2方法,得出如下的结果信息。
BINGHE
我们再来实现字符串截取的操作,如下所示。
@Test public void test3(){ String value = stringHandler("binghe", (s) -> s.substring(1, 3)); System.out.println(value); }
注意:需求中是按照第2个和第4个索引位置进行截取子串,字符串的下标是从0开始的,所以这里截取字符串时使用的是substring(1, 3),而不是substring(2, 4),这也是很多小伙伴容易犯的错误。
另外,使用上述Lambda表达式形式,可以实现字符串的任意处理,并返回处理后的新字符串。
运行test3方法,结果如下所示。
in
案例三
需求
1.声明一个带两个泛型的函数式接口,泛型类型为,其中,T作为参数的类型,R作为返回值的类型。
2.接口中声明对象的抽象方法。
3.在TestLambda类中声明方法。使用接口作为参数计算两个long型参数的和。
4.再就按两个long型参数的乘积。
实现
首先,我们按照需求定义函数式接口MyFunc,如下所示。
@FunctionalInterface public interface MyFunc<T, R> { R getValue(T t1, T t2); }
接下来,我们在TestLambda类中创建一个处理两个long型数据的方法,如下所示。
public void operate(Long num1, Long num2, MyFunc<Long, Long> myFunc){ System.out.println(myFunc.getValue(num1, num2)); }
我们可以使用下面的方法来完成两个long型参数的和。
@Test public void test4(){ operate(100L, 200L, (x, y) -> x + y); }
运行test4方法,结果如下所示。
300
实现两个long型数据的乘积,也很简单。
@Test public void test5(){ operate(100L, 200L, (x, y) -> x * y); }
运行test5方法,结果如下所示。
20000
看到这里,我相信很多小伙伴已经对Lambda表达式有了更深层次的理解。只要多多练习,就能够更好的掌握Lambda表达式的精髓。