[Java8 New Features] Lambda Expression

1. What is a Lambda expression?

"Lambda expression" (lambda expression) is an anonymous function. Lambda expression is named after the lambda calculus in mathematics, which directly corresponds to the lambda abstraction. It is an anonymous function, that is, a function without a function name. Lambda expressions can represent closures (note that it is different from the traditional mathematical sense).

2. Why use Lambda expressions?

Personal understanding: because of simplicity, save code

3. Lambda expression usage:

  • 1. The basic syntax of lambda expressions: A new operator "->" was introduced in java8 to change the operator to be called the arrow operator or the lambda operator
  • The arrow operator splits a lambda expression into two parts
  • Left: parameter list of the lambda expression
  • Right: The function learned to perform in the lambda expression, the lambda body
  • Syntax format 1: no parameters, no return value
    ()->System.out.println("Hello Lambda!");
  • Syntax format 2: There is one parameter and no return value
    (x)->System.out.println("Hello Lambda!");
  • Grammar format 3: If there is only one parameter, () can be omitted without writing
    x->System.out.println("Hello Lambda!");
  • Syntax format 4: There are more than two parameters, there is a return value, and there are multiple statements in the lambda body
  • Syntax Format 5: If there is only one statement in the lambda body, both return and {} can be omitted or not written
  • Syntax format 6: The data type of the parameter list of the lambda expression can be omitted, because the JVM compiler infers the data type through the context, that is, "type inference"
    (x , y) -> Integer.compare(x, y) ;
  • Two: lambda expressions need the support of "functional interfaces"
  • Functional interface: An interface with only one abstract method can use the annotation @FunctionalInterface to become a functional interface

4. Lambda expression application and comparison

Suppose, we now have a requirement: to obtain the information of employees whose age is greater than 35 in the current company

Employee Information:

    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)
            );

The most general approach: write a method to determine age, and then pass in employee information when testing

    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());
        }
    }

But now there is a need to obtain the information of employees whose salary is greater than 5,000 in the current company. At this time, we need to write another method to judge the salary.

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;
    }

Disadvantage: If you add other requirements, you also need to add new methods, which creates a lot of redundancy.

Optimization method one: strategy mode

Create an interface for method calls to implement

public interface MyPredicate<T> {

    public boolean test(T t);
}

Implementing an interface with methods

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;
    }

call the written method

@Test
    public void test4() {
        List<Employee> list = filterEmployee(employees,new FilterEmployeeByAge());

        for(Employee employee : list) {
            System.out.println(employee.getAge());  
        }
    }

Disadvantage: When adding new requirements, you need to add new interfaces

Optimization method 2: anonymous inner class

    @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);
        }

    }

Optimization method three: Lambda expression

@Test
    public void test6() {
        List<Employee> list = filterEmployee(employees, (e) -> e.getSalary()>=3000 );
        list.forEach(System.out::println);  
    }

The problem solved in two sentences is very simple and there is no wood!
The employees passed in the lambda expression is equivalent to the t variable passed in by the MyPredicate interface in method 1, and (e) -> e.getSalary()>=3000 is equivalent to the implementation of the MyPredicate interface.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324687925&siteId=291194637