java8 lambda expression
Lambda is an anonymous function, first compare it with the following specific examples
1. Anonymous inner class
Original method
import org.junit.Test;
public class TestLambda {
@Test
public void test1() {
Comparator<Integer> comparator = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
TreeSet<Integer> ts = new TreeSet<>(comparator);
}
}
Lambda expression optimization
@Test
public void test2(){
Comparator<Integer> comparator = (x,y)-> Integer.compare(x,y);
TreeSet<Integer> treeSet = new TreeSet<>(comparator);
}
1.1 Actual case:
Filter out the
Employee category of people who are older than 30 in a company
@Data
@AllArgsConstructor
public class Employee {
private String name;
private Integer age;
private double salary;
}
1.1.1 Original method
testing method
@Test
private void test3(){
Comparator<Integer> comparator = (x,y)-> Integer.compare(x,y);
TreeSet<Integer> treeSet = new TreeSet<>(comparator);
List<Employee> employees = Arrays.asList(
new Employee("张三",20,88.8),
new Employee("李四",30,88.8),
new Employee("王五",25,88.8),
new Employee("赵六",35,88.8),
new Employee("孙七",40,88.8)
);
List<Employee> result = filterByAge(employees);
System.out.println(result);
}
//筛选方法
public List<Employee> filterByAge(List<Employee> employees){
List<Employee> result = new ArrayList<>();
for (Employee em : employees) {
if (em.getAge()>30){
result.add(em);
}
}
return result;
}
If there are multiple separate conditions to filter, so a lot of filterBy methods are needed, and the repetition rate is high
Optimization method one:
1.1.2 Use design patterns
Define the interface
public interface MyPredicate<T> {
public boolean test(T t);
}
Implement the interface
public class FilterEmployeeByAge implements MyPredicate<Employee> {
@Override
public boolean test(Employee employee) {
return employee.getAge()>30;
}
}
Filtering method
public List<Employee> filter(List<Employee> employees,MyPredicate<Employee>mp){
List<Employee> result = new ArrayList<>();
for (Employee employee: employees) {
if (mp.test(employee)){
result.add(employee);
}
}
return result;
}
testing method
@Test
public void test4(){
List<Employee> employees = Arrays.asList(
new Employee("张三",20,88.8),
new Employee("李四",30,88.8),
new Employee("王五",25,88.8),
new Employee("赵六",35,88.8),
new Employee("孙七",40,88.8)
);
List<Employee> result = filter(employees, new FilterEmployeeByAge());
System.out.println(result);
}
1.1.3 Use anonymous inner classes based on design patterns
Filtering method
public List<Employee> filter(List<Employee> employees,MyPredicate<Employee>mp){
List<Employee> result = new ArrayList<>();
for (Employee employee: employees) {
if (mp.test(employee)){
result.add(employee);
}
}
return result;
}
testing method
@Test
public void test5(){
List<Employee> employees = Arrays.asList(
new Employee("张三",20,88.8),
new Employee("李四",30,88.8),
new Employee("王五",25,88.8),
new Employee("赵六",35,88.8),
new Employee("孙七",40,88.8)
);
List<Employee> result = filter(employees, new MyPredicate<Employee>() {
@Override
public boolean test(Employee employee) {
return employee.getAge()>30;
}
});
System.out.println(result);
}
1.1.4 Lambda expression optimization
Filtering method
public List<Employee> filter(List<Employee> employees,MyPredicate<Employee>mp){
List<Employee> result = new ArrayList<>();
for (Employee employee: employees) {
if (mp.test(employee)){
result.add(employee);
}
}
return result;
}
testing method
@Test
public void test6(){
List<Employee> employees = Arrays.asList(
new Employee("张三",20,88.8),
new Employee("李四",30,88.8),
new Employee("王五",25,88.8),
new Employee("赵六",35,88.8),
new Employee("孙七",40,88.8)
);
List<Employee> result = filter(employees,(employee) ->employee.getAge()>30);
System.out.println(result);
}
1.1.5 Use stream optimization
No filtering method required
@Test
public void test7(){
List<Employee> employees = Arrays.asList(
new Employee("张三",20,88.8),
new Employee("李四",30,88.8),
new Employee("王五",25,88.8),
new Employee("赵六",35,88.8),
new Employee("孙七",40,88.8)
);
employees.stream()
.filter((e)->e.getAge()>30)
.forEach(System.out::println);
}
2. Expression grammar
->
The lambda expression operator, divides the entire expression into two parts, the left is the parameter list, and the right is the lambda body
When using variables of the same level, the variables are final modified by default
2.1 Grammar format one
No parameters and no return value
Lambda expressions need interface support. The interface here is just an example, corresponding to no return value and no parameters, which does not represent actual meaning
@Test
public void test1() {
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
};
r1.run();
System.out.println("********************");
Runnable r2 = ()-> System.out.println("hello");
r2.run();
}
2.2 Syntax 2
One parameter, no return value
@Test
public void test2() {
Consumer consumer = (e)-> System.out.println(e);
consumer.accept("hello");
}
The Consumer interface is a functional interface that specifically supports lambda expressions. The specific performance is:
using @FunctionalInterface
annotations, the interface only consumes. The
main method is accept(), which passes in a parameter and has no return value.
2.3 Grammar Format Three
There are more than two parameters, there are return values, and there are multiple execution statements. The
execution statements need to be wrapped in braces
@Test
public void test3() {
Comparator<Integer> comparator = (x,y)->{
System.out.println("hello");
return Integer.compare(x,y);
};
comparator.compare(3,5);
}
Comparator is also a functional interface
2.4 Syntax 4
If there is only one parameter, the parentheses can be omitted, but it is customary to write
@Test
public void test2() {
Consumer consumer = e-> System.out.println(e);
consumer.accept("hello");
}
2.5 Syntax 5
There is only one statement in the lambda body, and the braces and return can be omitted
@Test
public void test4() {
Comparator<Integer> comparator = (x,y)->Integer.compare(x,y);
comparator.compare(3,5);
}
3. Functional interface
An interface with only one abstract method in the interface is called a functional interface. @FunctionalInterface
You can use annotations to check whether the interface is a functional interface or
the four built-in functional interfaces in java.
3.1 Consumer interface
void accept(T t)
@Test
public void test1(){
consumer(10,(e)->{
System.out.println("输入的是"+e);
});
}
/**
* 定义一个方法
*/
private void consumer(Integer num , Consumer<Integer> consumer){
consumer.accept(num);
}
3.2 Supplier supply interface
T get()
@Test
public void test2(){
List<Integer> getlist = getlist(10, () -> (int) (Math.random()*100));
System.out.println(getlist);
}
private List<Integer> getlist(Integer num , Supplier<Integer> supplier){
List<Integer> list = new ArrayList();
for (int i = 0; i <num ; i++) {
Integer integer = supplier.get();
list.add(integer);
}
return list;
}
3.3 Function interface
R accept(T t)
@Test
public void test3(){
String lsdadasd = strHandler("lsdadasd", (str) -> str.toUpperCase());
System.out.println(lsdadasd);
}
private String strHandler(String string , Function<String,String> function){
return function.apply(string);
}
3.4 Predicate interface
boolean test(T t)
public void test4(){
List<String> list =Arrays.asList("l1","li2","lis3","list4");
List<String> result = strFilter(list, (str) -> str.length() > 3);
System.out.println(result);
}
private List<String> strFilter(List<String> list , Predicate<String> predicate){
List<String> result = new ArrayList<>();
for (String str:list) {
if (predicate.test(str)){
result.add(str);
}
}
return result;
}