A preface

Lambda expressions are often used in daily development, such as:

public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1.5.10.4.2);
    // Prints each number in the list
    list.forEach((x) -> System.out.println(x));
}
Copy the code

Where (x) -> system.out.println (x) is the Lambda expression used. Lambda expressions can be divided into three parts:

  • Left parenthesis: Lambda’s parameter list, corresponding to the interface’s abstract method list.
  • Arrow: Operator of Lambda, which can be understood as a separator between the argument list and the Lambda body.
  • Lambda body: The implementation method body of the corresponding abstract method in the interface.

Did you notice that the Lambda body of the above example just calls an existing method and does nothing else? In this case, it is much clearer to refer to the existing method by a method name. As a result, a method reference is a more compact, readable version of a Lambda expression. The method reference operator is the double colon ::.

Using method references, the above example is written below, making it more compact and readable.

public static void main(String[] args) {
    List<Integer> list = Arrays.asList(1.5.10.4.2);
    // Prints each number in the list
    list.forEach(System.out::println);
}
Copy the code

Ii. Method Reference

A method reference refers to a method by its name. It can make the construction of the language more compact, reduce redundant code. The operator referenced by the method is the double colon ::. Method references are classified as follows:

type grammar Lambda expressions
Static method reference Class name :: Static method name (args) -> Class name. Static method names (ARGS)
Instance method reference Instance :: Name of the instance method (ARgs) -> instance. Instance method name (ARGS)
Object method reference Class name :: Object method name (INST, ARGS) -> Class name. Object method name (ARGS)
Build method reference The name of the class: : new (args) -> New class name (args)

Three practice

The following example uses the student class as an example. The student class is defined as follows:

public class Student {

    private String name;
    private Integer age;

    public static int compareByAge(Student s1, Student s2) {
        return s1.age.compareTo(s2.age);
    }

    // omit the property get/set method
}
Copy the code

3.1 Static method References

Let’s say we have 50 students in a list, and we want to sort them by age from youngest to oldest. We usually write a comparator to sort, as follows:

package com.nobody;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/ * * *@Description
 * @Author Mr.nobody
 * @Date 2021/3/7
 * @Version1.0 * /
public class Test {
    public static void main(String[] args) {

        List<Student> list = new ArrayList<>();
        // Add element elision, test can add itself
        / / sorting
        list.sort(new StudentAgeComparator());
    }
	// Compare the age of the student
    static class StudentAgeComparator implements Comparator<Student> {
        public int compare(Student s1, Student s2) {
            returns1.getAge().compareTo(s2.getAge()); }}}Copy the code

We find that the List’s sort method accepts the parameter Comparator as a functional interface, which can be changed to the following form with a Lambda expression:

list.sort((s1, s2) -> s1.getAge().compareTo(s2.getAge()));
Copy the code

The Student class has a static method called compareByAge that does the same thing as the Lambda expression, so we can change the above Lambda expression to the following form:

list.sort((s1, s2) -> Student.compareByAge(s1, s2));
Copy the code

As you can see, the final Lambda expression is a method that calls the Student class, so depending on the static method reference rules, it can be changed to the following form:

list.sort(Student::compareByAge);
Copy the code

3.2 Instance method references

That is, a method that refers to an existing instance. Static method reference classes are called by the class name without instantiation, whereas instance method references instantiate the object first.

If you change the Student static method compareByAge to a non-static method, that is:

public int compareByAge(Student s1, Student s2) {
    return s1.age.compareTo(s2.age);
}
Copy the code

You can sort the student array as follows:

list.sort(new Student()::compareByAge);
Copy the code

3.3 Object method References

Object method references can be used when the first argument in the argument list of a Lambda expression is the caller object of the instance method and the second argument is the argument of the instance method. For example, String equals() :

public static void main(String[] args) {
    BiPredicate<String, String> bp1 = (x, y) -> x.equals(y);
    boolean test1 = bp1.test("Mr.nobody"."Mr.anybody");
    System.out.println(test1);
    
    BiPredicate<String, String> bp2 = String::equals;
    boolean test2 = bp2.test("Mr.nobody"."Mr.anybody");
    System.out.println(test2);
}
Copy the code

For another example, we define the following instance method in the Student class that uses the toString method of the Srudent object.

public class Student {

    private String name;
    private Integer age;

    public static int compareByAge(Student s1, Student s2) {
        return s1.age.compareTo(s2.age);
    }

    // omit the property get/set method

    public void whoIam(a) {
        System.out.println("I am " + this.toString());
    }
    
    @Override
    public String toString(a) {
        return "Student{" +
                "name='" + name + '\' ' +
                ", age=" + age +
                '} '; }}Copy the code
public static void main(String[] args) {

    List<Student> list = new ArrayList<>();
    list.forEach(Student::whoIam);
}
Copy the code

3.4 Constructor reference

Note that the argument list of the referenced constructor is the same as the argument list of the abstract method in the functional interface.

public static void main(String[] args) {
    Supplier<Student> studentSupplier1 = () -> new Student();
    Student student1 = studentSupplier1.get();
    
    Constructor reference
    Supplier<Student> studentSupplier2 = Student::new;
    Student student2 = studentSupplier2.get();
}
Copy the code

Reference arrays are similar to reference constructors and are of type []::new, equivalent to lambda expressions x -> new int[x]. The type can be a primitive type or a class.

public static void main(String[] args) {
    
    Function<Integer, Student[]> studentFunction = Student[]::new;
    Student[] students = studentFunction.apply(10);
}
Copy the code

Four summarizes

A method reference refers to a method by its name. It can make the construction of the language more compact, reduce redundant code. The operator referenced by the method is the double colon ::

While method references can have some benefits, it is important to be careful about the context in which they are used, so there is no need to deliberately use method references. Lambda expressions can sometimes be more readable than method references, making it easier to change the code if necessary.


Welcome to wechat public account: “Java words” technical articles continue to update, please continue to follow……

  • Learn the latest technical articles as soon as possible
  • Get the latest technology learning materials video
  • Latest Internet information and interview experience