JDK1. Lambda expression of new features of 8

Posted by Duswa on Fri, 31 Dec 2021 13:29:43 +0100

Lambda is an anonymous function. We can understand lambda expression as a piece of code that can be passed (passing code like data). We can write more concise and flexible code. As a more compact code style, the language expression ability of Java has been improved.

1. How to write Lambda expressions

MyInterface interface (provide show method):

public interface MyInterface {
    void show();
}

Test class:

public class MyTest {
    public static void main(String[] args) {
        // Lambda expression, jdk1 After 8, provide a syntax style. You can think of it as a form of anonymous inner class, which can be passed as a parameter

        //Anonymous Inner Class 
        MyInterface myInterface = new MyInterface() {
            @Override
            public void show() {
                System.out.println("This is show method");
            }
        };

        //For the above anonymous inner class, we can use Lambda expression to simplify it

        MyInterface myInterface2 = () -> {
            System.out.println("This is show method");
        };
    }
}


2. Next step abbreviation of lambda's expression

public class MyTest2 {
    public static void main(String[] args) {
        //Lambda expressions, syntax for
        //Introduce an arrow symbol - >
        // Arrow - > divides the Lambda expression into left and right parts
        // To the left of the arrow is the formal parameter list of the abstract method in the interface
        // To the right of the arrow is the concrete rewriting logic of the abstract method

        // Writing of anonymous inner class
        Comparator<Integer> comparator = new Comparator<Integer>() {

            @Override
            public int compare(Integer a, Integer b) {
                return a - b;
            }
        };

        //First step abbreviation:
        Comparator<Integer> comparator2 = (Integer a, Integer b) -> {
            return a - b;
        };
        //The data type of the formal parameter can be omitted because there are generic types that can infer the data type of the formal parameter

        Comparator<Integer> comparator3 = (a, b) -> {

            return a - b;
        };

        //It can be simplified again
        //If your rewrite logic has only one line of code, {} return can be omitted
        Comparator<Integer> comparator4 = (a, b) -> a - b;
   }
}


3. How to write Lambda expression when parameters are passed in anonymous inner class

Iiterface interface:

public interface Iinterface {
    int test(int num);
}

Test class:

public class MyTest2 {
    public static void main(String[] args) {
        Iinterface iinterface = new Iinterface() {

            @Override
            public int test(int num) {
                return num + 10;
            }
        };

        Lambda expression,It shortens the anonymous inner class if there is only one formal parameter ()It can be omitted
        Iinterface iinterface2 = x -> x += 10;
    }
}


4. Anonymous inner classes are passed as parameters and Lambda expressions are passed as parameters

public class MyTest3 {
    public static void main(String[] args) {
        TreeSet<String> strings = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String a, String b) {
                return 0;
            }
        });


        TreeSet<String> strings2 = new TreeSet<>((a, b) -> a.compareTo(b));

        //You can choose alt+enter to replace it with an Lmabda expression
        TreeSet<String> strings3 = new TreeSet<>((a, b) -> a.compareTo(b));
    }
}


5. The definition of functional interface is: the interface that contains only one abstract method is called functional interface.

Use @ FunctionalInterface annotation on any functional interface to check whether it is a functional interface. Meanwhile, javadoc will also contain a declaration that the interface is a functional interface

If the following code is annotated, an error will be reported:

//@The functional interface will report an error if it is added
public interface HeHe {
    void aa();

    void bb();
}

Functional interface:

@FunctionalInterface //This annotation indicates that this is a functional interface
public interface HaHa {
    void test();
}

Test class:

public class MyTest {
    public static void main(String[] args) {
        //Lambda expressions need the support of functional interfaces. In other words, only functional interfaces can be written using lambda
        // Functional interface: there is only one abstract method in the interface, and an annotation @ FunctionalInterface can detect whether the interface is a functional interface

        HeHe heHe = new HeHe() {

            @Override
            public void aa() {

            }

            @Override
            public void bb() {

            }
        };


        HaHa haHa = new HaHa() {

            @Override
            public void test() {

            }
        };

        HaHa haHa2 = () -> System.out.println("aaaa");

    }
}


6. Four core functional interfaces provided in Java

Functional interface

Parameter type

Return type

purpose

Consumer<T>

Consumer interface

T

void

Apply operation to object of type T
Operation, including methods:
void accept(T t)

Supplier<T>

Supply type interface

nothing

T

Return an object of type T, package
Including method: T get();

Function<T, R>

Functional interface

T

R

Apply operation to object of type T
And return the result. result
Is an object of type R. Including Party
Method: R apply(T t);

Predicate < T > assertion interface

T

boolean

Determines whether an object of type T
Satisfies a constraint and returns
boolean value. Inclusion method
boolean test(T t);

Other functional interfaces:

Functional interface

Parameter type

Return type

purpose

BiFunction<T,U,R>

T U

R

Apply to parameters of type T, U
Operation to return a knot of type R
Fruit. The inclusion method is
R apply(T t, U u);

UnaryOperator<T>

(sub interface of Function)

T

T

An object of type T
A meta operation and returns a of type T
result. The inclusion method is
T apply(T t);

BinaryOperator<T>

(sub interface of BiFunction)

T T

T

Perform a second pass on an object of type T
A meta operation and returns a of type T
result. The inclusion method is
T apply(T t1, T t2);

BiConsumer<T,U>

T U

void

Apply to parameters of type T, U
Operation. The inclusion method is
void accept(T t, U u)

ToIntFunction<T>
ToLongFunction<T>
ToDoubleFunction<T>

T

int
long
double

Calculate int, long
double, function with value

IntFunction<R>
LongFunction<R>
DoubleFunction<R>

int
long
double

R

The parameters are int, long
Function of type double


7. Method reference:

Method reference: method reference is actually another way to write Lambda expressions,
When the operation to be passed to the Lambda body already has an implemented method, you can use the method reference
Note: the parameter list of the implementation abstract method must be consistent with the parameter list of the method reference method!
Method reference: use the operator "::" to separate the method name from the name of the object or class.


There are three main uses:

Object:: instance method
Class:: static method
Class:: instance method

public class MyTest {
    public static void main(String[] args) {
        Consumer<String> consumer = new Consumer<String>() {

            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("abc");

        Consumer<String> consumer2 = s -> System.out.println(s);
        consumer2.accept("hello");


        //Your rewriting logic system for the abstract method public void accept(String s) in the Consumer interface out. println(s)
        //Note: the abstract method accept(String s) has no return value and a parameter
        //Let's look at our rewriting logic
        //PrintStream out = System.out;
        //out.println("abc");
        //The return value type and parameter list of the println("abc") called are consistent with the return value type and parameter list of the accept(String s) method. If there is such a coincidence, it can be abbreviated as the following instance object:: method
        Consumer<String> consumer3 = System.out::println;


        System.out.println("==========================");

        BinaryOperator<Double> binaryOperator = new BinaryOperator<Double>() {

            @Override
            public Double apply(Double x, Double y) {
                return Math.max(x, y);
            }
        };

        //First abbreviation
        BinaryOperator<Double> binaryOperator2 = (x, y) -> Math.max(x, y);

        //The final abbreviation, because there is a coincidence rewriting
        //Observation: the apply abstract method in BinaryOperator has a return value and two parameters
        //Observe our rewrite logic math max(x, y);  The called Max method has a return value and two parameters, which can correspond to the apply abstract method

        //Final abbreviation, class name:: static method
        BinaryOperator<Double> binaryOperator3 = Math::max;

        System.out.println("==============================================");

        Comparator<String> comparator = new Comparator<String>() {

            @Override
            public int compare(String a, String b) {
                //The first parameter serves as the caller, and the second parameter serves as the incoming value
                return a.compareTo(b);
            }
        };
        //Step 1 abbreviation
        Comparator<String> comparator2 = (a, b) -> a.compareTo(b);

        //Final shorthand: the first parameter acts as the caller, and the second parameter acts as the incoming value
        Comparator<String> comparator3 = String::compareTo;


        System.out.println("=========================================");

        BiFunction<String, String, Boolean> biFunction = new BiFunction<String, String, Boolean>() {

            @Override
            public Boolean apply(String x, String y) {
                return x.equals(y);
            }
        };

        BiFunction<String, String, Boolean> biFunction2 = (x, y) -> x.equals(y);

        //Final abbreviation
        BiFunction<String, String, Boolean> biFunction3 = String::equals;

    }
}


8. Constructor reference:

Format: ClassName::new

Combined with functional interface, it is automatically compatible with methods in functional interface. The constructor reference can be assigned to the defined method, and the constructor parameter list should be consistent with the parameter list of the abstract method in the interface!

Student class:

public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Test class:

public class MyTest2 {
    public static void main(String[] args) {
        Supplier<Student> supplier = new Supplier<Student>() {

            @Override
            public Student get() {
                return new Student();
            }
        };

        Supplier<Student> supplier2 = () -> new Student();

        //Final shorthand observation: if the constructor can correspond to the return value and formal parameter list of the abstract method get() in the interface, you can use the constructor reference shorthand

        Supplier<Student> supplier3 = Student::new;
        System.out.println("==================================================");

        BiFunction<String, Integer, Student> biFunction = new BiFunction<String, Integer, Student>() {

            @Override
            public Student apply(String name, Integer age) {
                return new Student(name, age);
            }

        };
        Student wangwu = biFunction.apply("wangwu", 25);
        //First abbreviation
        BiFunction<String, Integer, Student> biFunction2 = (name, age) -> new Student(name, age);
        Student s0 = biFunction2.apply("lisi", 24);
        //Final abbreviation:

        BiFunction<String, Integer, Student> biFunction3 = Student::new;

        Student s = biFunction3.apply("Zhang San", 23);

    }
}

Topics: Java Back-end