Detailed explanation of Java8 functional interface

catalogue

1, Supplier interface

1. Use Supplier directly

2. Use Supplier to generate objects

3. Take Supplier as the parameter of the method

2, Consumer interface

1. Use the Consumer object directly

2. Consumer as parameter

3. Use Consumer as the parameter

3, Predict interface

1. test() method demonstration

2. Default method and()

3. Default method (or)

4. Default method negate()

5. Static method isEqual()

6. Application example of predict

4, Function interface

1. Abstract method: apply()

2. Default method: andThen()

3. Default method: compose()

5, BinaryOperator interface

1. Method demonstration: apply()

2. BinaryOperator interface as method parameter

3. Demonstration of static methods

6, UnaryOperator interface

Parameters of the method used by UnaryOperator

7, Summary of common functional interfaces

Java 8 functional interface

Interfaceparameterreturnchineseexample
Supplier NoneTProviderCreate objects using factory methods
Consumer TNoneconsumerConsume one data, no return
Predicate TbooleanJudgment / predicateTest the specified conditions
Function TRfunctionGet another parameter value from one parameter

1, Supplier interface

The Supplier interface represents the provider of a result.

The Supplier interface is used to generate data. The type of data is given by generic parameters, and the return value is obtained by using the get() method.

The source code of the interface is as follows:

@FunctionalInterface
public interface Supplier<T> {
    /**
     * Get a result and return the T object
     * @return a result
     */
    T get();
}

Methods in the Supplier interface

T get() Gets the specified type of data

1. Use Supplier directly

Case requirements: the basic use of the get() method. In the Supplier interface, the get method returns a string.  

Case steps:

  1. Create a Supplier object using Lambda. The generic type is String. The method body returns a String. return can be omitted.
  2. Call the Supplier's get() method to get the string and print it out
public class LambdaTest {
    public static void main(String[] args) {
        //Creating a Supplier object using Lambda
        Supplier supplier = () -> "Hello Java!";
        //Output its value
        System.out.println(supplier.get());
    }
}
// output
// Hello Java!

2. Use Supplier to generate objects

Case requirements:

The following example demonstrates how to generate an employee object return by calling a static method. Use the constructor as a reference to the Supplier parameter.

Case steps:

  1. Create a private static Employee object inside the main class, override the toString() method, and return a string: "I am an Employee".
  2. Create a Supplier object in the main function, and the generic type is Employee. Use Lambda to pass in the Supplier object, instantiate the Employee object in the method body, and omit the return method.
  3. Use the get() method of the supplier object to get the employee object
  4. Print out employee objects

Because the Employee object is private, external classes cannot directly instantiate the Employee object.

Call the Supplier's get() method to generate the employee object. The purpose of this is to control the generation method of the employee object, similar to the factory mode.

public class LambdaTest {

    public static void main(String[] args) {
        //If you use Lambda to pass in the Supplier object, an employee object will be generated
        //At this time, only the interface is instantiated and the code inside is not executed
        Supplier supplier = ()->new Employee();
        //Output employee object
        System.out.println(supplier.get());
    }

    //Employee category
    private static class Employee {//Pay attention to static
        @Override
        public String toString() {
            return "I'm an employee";
        }
    }
}
// output
// I'm an employee

3. Take Supplier as the parameter of the method

Requirement Description: find the maximum value in the array, use the Supplier interface as the method parameter type, and find the maximum value in the int array through Lambda expression.

Demand analysis:

  1. Define integer array int [] arr = {12,68,10,2,99313,46};
  2. Create static method getMax(): return int type, take Supplier as parameter, the generic type is Integer, and the method body calls get() method to return value.
  3. In the main function, we call the getMax() method, use Lambda to import the Supplier object, and realize the function of finding the maximum value.
  4. The Lambda expression is equivalent to the method body: traverse each element, compare the size, and find the maximum value.
public class LambdaTest {

    public static void main(String[] args) {
        int[] arr = {12, 68, 10, 2, 99, 313, 46};
        // Call the getMax method to get the maximum value. Lambda is equivalent to the method body
        int num = getMax(() -> {
            int max = arr[0];
            for (int i = 1; i < arr.length; i++) {
                if (max < arr[i]) {
                    max = arr[i];
                }
            }
            return max;
        });
        //Maximum output
        System.out.println("The maximum value is:" + num);
    }
    
    //Use Supplier as parameter
    public static int getMax(Supplier<Integer> supplier) {
        return supplier.get();
    }
}
// output
// The maximum value is 313

2, Consumer interface

The Consumer interface represents a class of operations that accept a single input variable and have no return value. Its function is opposite to that of a Supplier. It consumes data. The data type of consumption needs to be specified through generics.

The source code is as follows:

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Accept t object, no return value
     */
    void accept(T t);

    /**
     * The default combination method, parameters and return values are of Consumer type
     * First call your own accept() method, and then call the accept() method of the parameter
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Methods in the Consumer interface

void accept(T t) Accepts the operation on the given parameter.

Default methods in the Consumer interface:

default Consumer<T>  andThen(Consumer<T>  after)

If the parameters and return values of a method are all of consumer < T > type, the effect can be achieved:

When consuming a data, first do one operation, and then do another operation. The two operations are executed in turn to realize a combined operation. This method is the default method andThen in the Consumer interface.

1. Use the Consumer object directly

Implementation steps:

  1. Create a Consumer object using Lambda to print the incoming string data directly.
  2. Call the accept() method of the Consumer, and pass in a string data in the accept() method.
public class LambdaTest {

    public static void main(String[] args) {
        //Create a Consumer object and print the passed in variable t
        Consumer consumer = t -> System.out.println(t);
        //Call the method in the Consumer
        consumer.accept("Hello Lambda");
    }
}
// output
// Hello Lambda

2. Consumer as parameter

The parameter of the forEach method traversed in the List and Set sets is Consumer. Please see the following code:

Case requirements:

  1. Create an array using arrays Aslist ("Monkey King", "pig Bajie", "Baigujing", "Chang'e") is converted into a List object.
  2. Use the forEach method to print each element, and use the Lamba expression in forEach to output the incoming string
public class LambdaTest {
    public static void main(String[] args) {
        //Convert array to List object
        List<String> names = Arrays.asList("Sun WuKong", "Zhu Bajie", "Baigujing", "Chang'e");
        //Print each string, and the parameter of forEach is Consumer
        names.forEach(t -> System.out.println(t));
    }
}
// output
//Sun WuKong
//Zhu Bajie
//Baigujing
//Chang'e

Analyze the source code of the forEach() method

default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

This is defined in Java The default method in the lang. Iterable interface. The parameter is the Consumer object. The method body uses for to traverse the current collection, and this is the collection object. The accept() method is called one element at a time. We implement the accept() method in the external calling code and output each element.

public static # T requireNonNull(T obj) static method, a new method in JDK7, determines whether the incoming object is NULL. If it is NULL, an exception is thrown. If it is not NULL, the object itself is returned. It is often used to verify the passed in object parameters in methods or construction methods.

default Consumer<T>  andThen(Consumer<? super T>  after) {
     //Determine whether after is null
     Objects.requireNonNull(after);
     //First call your own accept() method, and then call the accept() method of the parameter
     return (T t) -> { accept(t); after.accept(t); };
}
​
To achieve composition, you need two or more Lambda Expression, and andThen The semantics of is to perform "step by step" operations.

Case requirements: print the string hello first in uppercase Hello, and then in lowercase hello

Implementation steps:

  1. Create the Consumer object c1 and print the uppercase of the s object using Lambda
  2. Create the Consumer object c2 and print the lowercase of the s object using Lambda
  3. c1 calls the andThen(c2) method, and then calls accept("string") to complete the sequential operations.
public class LambdaTest {
    public static void main(String[] args) {
        //Print uppercase
        Consumer<String> c1 = s -> System.out.println(s.toUpperCase());
        //Print lowercase
        Consumer<String> c2 = s-> System.out.println(s.toLowerCase());
        //Call method
        c1.andThen(c2).accept("Hello Consumer");
    }
}
// output
// HELLO CONSUMER
// hello consumer

3. Use Consumer as the parameter

Requirements Description:

Format the print information. There are multiple pieces of information in the following string array. Please follow the format "Name: XX. Gender: XX." Print the information in a format. It is required to take the action of printing name as the Lambda instance of the first Consumer interface and the action of printing gender as the Lambda instance of the second Consumer interface, and "splice" the two Consumer interfaces together in order. The following array consists of 5 elements, each containing 2 items of information, separated by commas.

String[] arr = {"Zhang Fei, male", "Diao Chan, female", "Cao Cao, male", "sun Shangxiang, female", "Xiao Qiao, female"};

Implementation steps

  1. Create a static method printInfo(), which has three parameters. The first is the string array to be printed, the second is the Consumer to print the name, and the third is the Consumer to print the gender.
  2. Traverse each element in the array in the printInfo method, and then call name andThen(gender). Accept (single element)
  3. Each time the andThen() method is called, a horizontal line is output below
  4. Create the array to be traversed above in the main function
  5. Call the printInfo method and pass in three parameters. The first parameter is the array, the second parameter uses Lambda to print the name, and the parameter s represents each element in the array. The third parameter uses Lambda to print gender.
public class LambdaTest {

    public static void main(String[] args) {
        String[] arr = {"Fei Zhang,male", "army officer's hat ornaments,female", "Cao Cao,male","Sun Shangxiang,female"};
        //s here represents each element in the array
        printInfo(arr,
                s ->System.out.println("full name:" + s.split(",")[0]),
                s ->System.out.println("Gender:" + s.split(",")[1]));
    }

    public static void printInfo(String[] arr, Consumer<String> name, Consumer<String> gender) {
        for (String s : arr) {
            name.andThen(gender).accept(s);
            System.out.println("------------------");
        }
    }
}

3, Predict interface

Predict means Predicate in Chinese, "I'm a programmer", "yes" or "no" is the Predicate.

It represents a function with only one variable and returns boolean type. Sometimes we need to make some judgment to get a Boolean value. You can use Java util. function. Predict interface.

@FunctionalInterface
public interface Predicate<T> {

    /**
     * Abstract method, test t and return boolean type
     */
    boolean test(T t);

    /**
     * Combination method, short circuit the current predicate with another predicate, and return a predicate object
     */
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    /**
     * Perform a logical non operation on the current predicate and return a predicate object
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    /**
     * Combination method, short circuit the current predicate with another predicate, and return a predicate object
     */
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    /**
     * Static method to judge whether the object passed in by the test(object) method is equal to the parameter targetRef object
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

Methods in predict interface

boolean test(T t) yes t Test the specified conditions and return boolean type

1. test() method demonstration

Case requirements: judge whether the parameter length given by the test("string") method is greater than 5

Case steps:

  1. Create a Predicate predicate object and use Lambda to implement the Boolean test (T) method
  2. The parameter of the method body is s, the length of the returned string is greater than 5, and the return keyword is omitted.
  3. Call the test() method twice to see the running results. For the first time, use the string Hello and for the second time, use the string predict
public class LambdaTest {

    public static void main(String[] args) {
        //Create a Predicate predicate object. The Boolean test (T) method receives the string type and returns the boolean type
        Predicate<String> predicate = s -> s.length() > 5;
        //Call the test method twice to see the running result
        System.out.println("Hello Is the length greater than 5:" + predicate.test("Hello"));
        System.out.println("Predicate Is the length greater than 5:" + predicate.test("Predicate"));
    }
}
// results of enforcement
// Is the length of Hello greater than 5: false
// Is the length of Predicate greater than 5: true

2. Default method and()

Since it is conditional judgment, there will be three common logical relationships: and, or and non. The default method and can be used when two Predicate conditions are connected with and logic to achieve the effect of "and". This default method receives a Predicate parameter and returns a Predicate parameter.

Its JDK source code is:

/**
     * Combination method, short circuit the current predicate with another predicate, and return a predicate object
     */
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

and method demonstration example:

Case requirements: judge whether a string contains the specified string: both uppercase "H" and uppercase "W"

Case steps:

  1. Create 2 strings to be judged: s1="Hello world" and s2="Hello World"
  2. Using a Lambda expression, create two Predicate objects
  3. Judge whether the string s contains H
  4. Judge whether the string s contains W
  5. Call the and method and test method to output s1 and s2 results respectively
public class LambdaTest {

    public static void main(String[] args) {
        //Create 2 strings to be judged
        String s1 = "Hello world";
        String s2 = "Hello World";
        // Using a Lambda expression, create two Predicate objects
        //Judge whether s contains H
        Predicate<String> p1 = s -> s.contains("H");
        //Judge whether s contains W
        Predicate<String> p2 = s -> s.contains("W");
        //Call the and method
        System.out.println(s1 + "Include H and W: " + p1.and(p2).test(s1));
        System.out.println(s2 + "Include H and W: " + p1.and(p2).test(s2));
    }
}
// Output results
// Does Hello world contain H and W: false
// Does Hello World contain H and W: true

3. Default method (or)

Similar to the and of and, the default method or implements the or operation in the logical relationship. This default method receives a Predicate parameter and returns a Predicate parameter.

The JDK source code is:

/**
     * Combination method, short circuit the current predicate with another predicate, and return a predicate object
     */
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

or method demonstration example:

Case requirements: judge whether the length of a string is greater than 10 or less than 5

Case steps:

  1. Create three strings S1, S2 and S3, as shown in the following figure
  2. Use Lambda to create two Predicate interface objects. The first determines whether the length is greater than 10 and every two determines whether the length is less than 5
  3. Call the or and test methods to output the test results of each string
public class LambdaTest {

    public static void main(String[] args) {
        //Create three strings
        String s1 = "Hello World"; //Greater than 10
        String s2 = "Java"; //Less than 5
        String s3 = "I am boy"; //Not more than 10 and not less than 5

        //Create 2 Predicate interface objects using Lambda
        Predicate<String> p1 = s -> s.length() > 10;
        Predicate<String> p2 = s -> s.length() < 5;

        //Output test results for each string
        System.out.println(s1 + "=" + p1.or(p2).test(s1));
        System.out.println(s2 + "=" + p1.or(p2).test(s2));
        System.out.println(s3 + "=" + p1.or(p2).test(s3));
    }
}
// Output results
// Hello World=true
// Java=true
// I am boy=false

4. Default method negate()

"And" and "or" have been understood, and the remaining "not" (negative) will also be simple. The method has no parameters and the return value is predict.

The JDK source code of the default method negate is:

/**
     * Perform a logical non operation on the current predicate and return a predicate object
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
It is easy to see from the implementation that it is executed test After the method, the results boolean Value proceed“!"Take it instead.
​
To be in test Call before method invocation negate Method, as and and or The method is the same.

Case requirements: judge whether the age is less than 18 years old and take the judgment result inversely.

Case steps

  1. Create 2 integer types of ages, one 25 and one 15.
  2. Create a Predicate using Lambda to judge that the age is less than 18 years old.
  3. Use the negate () method and then call the test() method to output the results of two ages
public class LambdaTest {

    public static void main(String[] args) {
        int age1 = 25; //25 years old
        int age2 = 15; //15 years old

        Predicate<Integer> predicate = (a) -> a < 18; //Judge whether he is less than 18 years old
        System.out.println(age1 + "Less than 18 years old, reverse:" + predicate.negate().test(age1));
        System.out.println(age2 + "Less than 18 years old, reverse:" + predicate.negate().test(age2));
    }
}
// results of enforcement
// If 25 is less than 18 years old, take the inverse: true
// 15 less than 18 years old, negative: false

5. Static method isEqual()

The only static method in Predicate. The parameters of the method are two Object types and return a Predicate type.

Function: according to objects The equals (object, object) method compares whether the two parameters are equal,

One object is passed in through isEqual() and the other object is passed in through test().

// ​java. util. Method description in objects class
public static boolean equals(Object a,Object b)

Function: used to compare whether two objects are equal

Parameters: a and b are the two objects to compare

Return: if two objects are equal, return true; otherwise, return false

The JDK source code is:

/**
     * Static method to judge whether the object passed in by the test(object) method is equal to the parameter targetRef object
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }

Case requirements: compare whether two strings are equal

Case steps:

  1. Directly return the Predicate object through the static method isEqual("newboy")
  2. Call the test() method in predict to pass in another two strings for comparison
public class LambdaTest {
    public static void main(String[] args) {
        //The predict object is returned directly through a static method
        Predicate predicate = Predicate.isEqual("newboy");

        //Call the test() method to pass in another two strings for comparison
        System.out.println("Whether the two strings are equal:" + predicate.test("newboy"));
        System.out.println("Whether the two strings are equal:" + predicate.test("NewBoy"));
    }
}
// results of enforcement
// Whether two strings are equal: true
// Whether the two strings are equal: false

6. Application example of predict

Requirements Description:

There are multiple "name + gender" information in the set as follows: "Zhang Fei, male", "Diao Chan, female", "Cao Cao, male", "sun Shangxiang, female", "Xiao Qiao, female". Please filter the qualified strings into the set ArrayList through the and combination method of the Predicate interface. Two conditions need to be met at the same time:

  • Must be a girl
  • The name is two words

Development steps:

  1. Create the first Predicate judgment condition: the length of the 0-th element name separated by commas is 2
  2. Create the second Predicate judgment condition: the first element separated by commas has gender equal to female
  3. Create a new List collection to store qualified strings after filtering
  4. Use forEach(Lambda) in the List to traverse the original List set above, and use the and and test methods in predict to judge each element
  5. Both conditions are true and added to the new List collection
  6. Create the first Consumer interface and output the names of the 0th element separated by commas
  7. Create the second Consumer interface and output the first element separated by commas
  8. Use forEach(Lambda) in the List to traverse and output the filtered new collection
  9. Use the andThen and accept methods in the Consumer interface to output each element
public class LambdaTest {
    public static void main(String[] args) {
        //Create a List collection from the array
        List<String> list = Arrays.asList("Fei Zhang,male", "army officer's hat ornaments,female", "Cao Cao,male","Sun Shangxiang,female","Little Joe,female");

        //Create the first Predicate judgment condition: the length of the 0-th element name separated by commas is 2
        Predicate<String> pname = s -> s.split(",")[0].length() ==2;
        //Create the second Predicate judgment condition: the first element separated by commas has gender equal to female
        Predicate<String> pgender = s-> s.split(",")[1].equals("female");

        //Create a new List collection
        List<String> infos = new ArrayList<>();
        //Use forEach() in Lamba to traverse the List collection above
        //Use the and and test methods in predict to determine each element
        list.forEach(s -> {
            //Both are genuine talents added to the collection
            if (pname.and(pgender).test(s)) {
                infos.add(s);
            }
        });
        //Create the first Consumer interface and output the names of the 0th element separated by commas
        Consumer<String> cname = s -> System.out.println("full name:" + s.split(",")[0]);
        //Create the second Consumer interface and output the first element separated by commas
        Consumer<String> cgender = s -> System.out.println("Gender:" + s.split(",")[1]);
        //Use forEach() in Lamba to traverse and output the filtered collection
        infos.forEach(s -> {
            //Use the andThen and accept methods in the Consumer interface, one line apart for each output element
            cname.andThen(cgender).accept(s);
            System.out.println("---------------");
        });
    }
}
// Output results
 Name: Diao Chan
 Gender: Female
---------------
Name: Xiao Qiao
 Gender: Female
---------------

4, Function interface

Function interface:

Get another parameter value according to one parameter, which is called the calculated parameter in the front and the calculated result in the back.

There are in and out, so it is called "Function".      

Similar to a function in mathematics, the value of one variable is obtained from another. For example: f(x) = 2x+3

The following is its Java source code:

// A function that represents the result of one variable from another
@FunctionalInterface
public interface Function<T, R> {

    /**
     * Calculate the given variable t to get the returned result R
     */
    R apply(T t);

    /**
     * The default combination method is to calculate the current function first and then the incoming function
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    /**
     * The default combination method is to calculate the incoming function first, and then the current function
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    /**
     * Static method: always returns its input variable
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

1. Abstract method: apply()

It's Java util. function. Methods in function interface

​R apply(T t); Calculate the given variable t to get the returned result R

Demo example of apply method:

Case requirements: convert Integer type to String type, and output the length of the converted String.

  1. Create a Function object. The input type is integer and the output type is string
  2. Lambda expressions convert an integer i into a string
  3. Call the apply (number) method to get the converted String, and then call the length() method of the string to get the length and print out
  4. The number 99 is converted for the first time, and the number 1000 is converted for the second time
public class LambdaTest {
    public static void main(String[] args) {
        //Create a Function object
        Function<Integer,String> converter = i -> Integer.toString(i);
        System.out.println("99 The length of conversion to string is:" + converter.apply(99).length());
        System.out.println("1000 The length of conversion to string is:" + converter.apply(1000).length());
    }
}
// Output results
99 The length of conversion to string is: 2
1000 The length of conversion to string is: 4

2. Default method: andThen()

There is a default andThen method in the Function interface, which is used for combination operations. ​

First calculate the current function, and then calculate the incoming function. The two functions are executed in turn. ​

The parameter of andThen method is a Function object, which returns a Function object.

JDK source code:

    /**
     * The default combination method is to calculate the current function first and then the incoming function
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

Case requirements:

There are two consecutive operations: the first operation is to convert the string into an int number, and the second operation multiplies the converted number by 10. The two operations are combined in sequence.

  1. Let the user input a number from the keyboard and receive it with a string.
  2. Create the first Function function to convert the string to an integer
  3. Create the second function and multiply the integer by 10 to return
  4. Call the andThen method and apply, and output the result
public class LambdaTest {
    public static void main(String[] args) {
        //The user enters a string
        System.out.println("Please enter a number:");
        Scanner input = new Scanner(System.in);
        String str = input.nextLine();
        //The first function converts a string to an integer
        Function<String,Integer> f1 = s -> Integer.parseInt(s);
        //The second function multiplies the integer by 10 to return
        Function<Integer,Integer>  f2 = i -> i * 10;
        //Call the andThen method and output the result
        System.out.println("Converted to an integer and multiplied by 10, the result is:" + f1.andThen(f2).apply(str));
    }
}
// Output results
 Please enter a number:
2
 After converting to an integer and multiplying by 10, the result is: 20

3. Default method: compose()

Function has a compose method very similar to andThen.

Chinese means "composition". The method parameter is Function and the return value is Function. Run the apply method of the parameter first, and then call your own apply method.

Its JDK source code is:

    /**
     * The default combination method is to calculate the incoming function first, and then the current function
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
// Compared with the JDK source code implementation of andThen method, it can be found that the parameter Lamda of compose method will be executed first.
So the two are just different in order.

Demo of compose method

Case requirements:

Create two function objects: one to convert the string to uppercase and one to lowercase. Use the andThen and compose methods to combine calls to view different calculation results.  

Development steps:

  1. Create the first Function. The input and output are of String type. Convert the String to uppercase.
  2. Create the second Function. The input and output are of String type. Convert the String to lowercase.
  3. Call the apply method of the first function and output the value
  4. Call the apply method of the second function and output the value
  5. Call the andThen method and the apply method to view the running results
  6. Call the compose method and the apply method to view the running results
public class LambdaTest {
    public static void main(String[] args) {
        Function<String, String> f1 = s -> s.toUpperCase();
        Function<String, String> f2 = s -> s.toLowerCase();
        System.out.println("Convert to capital:" + f1.apply("Hello"));
        System.out.println("Convert to lowercase:" + f2.apply("Hello"));
        System.out.println("Convert to uppercase and then lowercase:" + f1.andThen(f2).apply("Hello"));
        System.out.println("Convert to lowercase and then uppercase:" + f1.compose(f2).apply("Hello"));
    }
}
// results of enforcement
 Convert to capital: HELLO
 Convert to lowercase: hello
 Convert to uppercase and then lowercase: hello
 Convert to lowercase and then uppercase: HELLO

Application example of Function

Requirement Description: please use Function to splice functions and execute multiple functions in order.

The operations are as follows:

  1. Intercept the digital age part of the string "Zhao Liying, 20" to obtain the string;
  2. Convert the string in the previous step into a number of type int;
  3. Accumulate the int number of the previous step by 100 to obtain the result int number.

Development steps:

  1. Create the first Function object, take out the string 20 and return a string
  2. Create the second Function object, convert the string to an integer, and return an integer
  3. Create the third Function object, add the integer by 100, and return the calculation result. 4) call the andThen method twice, apply the string: "Zhao Liying, 20", and output the result

code implementation

public class LambdaTest {
    public static void main(String[] args) {
        //Create the first Function object, take out the string 20 and return a string
        Function<String,String> fun1 = s -> s.split(",")[1];
        //Create the second Function object, convert the string to an integer, and return an integer
        Function<String,Integer> fun2 = s -> Integer.parseInt(s);
        //Create the third Function object, add the integer by 100, and return the calculation result
        Function<Integer,Integer> fun3 = num -> num + 100;
        //Call the andThen method twice, apply the string and output the result
        System.out.println("Calculation results:" + fun1.andThen(fun2).andThen(fun3).apply("Zhao Liying,20"));
    }
}
//Output results
 Calculation result: 120

5, BinaryOperator interface

BinaryOperator means to operate on two operands of the same type to produce the same type of results.

Methods in interfaces

static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) 
Return a BinaryOperator ,It is based on the specified Comparator Returns the larger of two elements Comparator .   
​
static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) 
return BinaryOperator Returns the smaller of the two components specified Comparator .   
​
Two static methods are defined in this interface,
BiFunction Is a function interface for defining two operators.

Methods in BiFunction interface

T apply(T t, T u); From parent interface BiFunction Abstract methods inherited from,
Pass in two parameters t and u Perform function calculation and return the calculation result.​
Both parameters and return values are of the same type.
​
default <V> BiFunction<T,U,V> andThen(Function<? super R,? extends V> after)
Returns a composite function that is first applied to its input, and then after Function is applied to the result. 
If the evaluation of any function throws an exception, it is forwarded to the caller of the composite function. 

1. Method demonstration: apply()

Case requirements:

Use the apply() method of the BinaryOperator interface to calculate the sum of two integers and output the result.

Case steps:

  1. Create class Demo25BinaryOperator
  2. Create a BinaryOperator interface and use Lambda to implement the method. The method has two parameters and returns the calculation result of the method.
  3. Call the apply() method to pass in the actual parameters and print the calculation results.

Case code:

public class LambdaTest {
    public static void main(String[] args) {
        BinaryOperator<Integer> operator = (m, n) -> m + n;
        System.out.println("The calculation result is:" + operator.apply(3, 5));
    }
}
// Output results
 The calculation result is: 8

Static method

ublic static  BinaryOperator minBy(Comparator comparator)
Through the back Comparator The comparator judges and returns the smaller of the two elements
​
public static  BinaryOperator maxBy(Comparator comparator)
Through the back Comparator The comparator judges and returns the larger of the two elements
​
Comparator Static method description in interface
naturalOrder() Compare by the size of the natural sorting of elements, and return a Comparator object
reverseOrder() Compares the size of elements in reverse order and returns a Comparator object

2. BinaryOperator interface as method parameter

Case requirements:

There is the following array {2,1,3,5} to replace each element in the array. The replacement algorithm is as follows:

  1. The 0th element remains unchanged
  2. The result of element 0 + element 1 replaces element 1
  3. The result of the first new element + the second element replaces the two
  4. The result of the second new element + the third element replaces the third
  5. And so on until all elements are replaced.
//Method description in the Arrays class
void parallelPrefix(T[] array, BinaryOperator op)

Function: use the specified binary operation function to replace each element in the array and accumulate in parallel
 Parameter 1: array to replace
 Parameter 2: specify binary operation function

Case steps

  1. Create BinaryOperator object, and the algorithm of specifying 2 numbers is m+n
  2. Create an array of Integer type: {2,1,3,5}
  3. Array before output operation
  4. Call the parallelPrefix() method above and pass in BinaryOperator as a parameter
  5. Array after output operation
  6. If different algorithms are used, the replacement result of each element is different. For example, multiply two numbers.

Case code

public class LambdaTest {
    public static void main(String[] args) {
        BinaryOperator<Integer> operator = (m,n) -> m+n;
        Integer [] arr = {2,1,3,5};
        System.out.println("Array before operation:" + Arrays.toString(arr)) ;
        Arrays.parallelPrefix(arr,operator);
        System.out.println("Array after operation:" + Arrays.toString(arr)) ;
    }
}
//Output results
 Array before operation:[2, 1, 3, 5]
Array after operation:[2, 3, 6, 11]

3. Demonstration of static methods

Case requirements:

Compare two integers, use the minBy static method to find the minimum value, compare two strings, and use the maxBy static method to find the maximum value

Case steps

  1. Create a BinaryOperator object and use the minBy() static method to compare the normal size of the number.
  2. Output the minimum value, call the apply() method, and pass in 2 integers.
  3. Create a BinaryOperator object and use the maxBy() static method to compare the size of the string.
  4. Output the maximum value, call the apply() method, and pass in two strings: "ABCD","xyz"

Case code

public class LambdaTest {
    public static void main(String[] args) {
        //naturalOrder() is a static method in Comparator that compares numbers by their normal size
        BinaryOperator oper1 = BinaryOperator.minBy(Comparator.naturalOrder());
        System.out.println("The minimum value is:" + oper1.apply(3,5));

        //naturalOrder() is a static method in Comparator that compares strings according to their normal size
        BinaryOperator oper2 = BinaryOperator.maxBy(Comparator.naturalOrder());
        System.out.println("The maximum value is:" + oper2.apply("ABCD","xyz"));
    }
}
// Output results
 The minimum value is: 3
 The maximum value is: xyz

6, UnaryOperator interface

UnaryOperator represents an operation on a single operand that produces the same result as its operand type.

The UnaryOperator interface inherits from the Function interface,

Therefore, there is a t apply (t t t) abstract method, which is the same as the apply() method in the previous Function interface.

Its input type and return type are the same type.

Source code of UnaryOperator interface

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

    /**
     * A unary operator that always returns its input parameters
     */
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}

Method demonstration

UnaryOperator Method description in interface
​
T apply(T t); 
    from Function The abstract method inherited from the interface applies this unary operation function with the given parameters and returns another value.
    Parameter and return value are of the same type.
​
static  UnaryOperator identity() 
    The unary operator that always returns its input parameters, that is, the subsequent operator apply()Return whatever you enter.

Case steps

  1. Use UnaryOperator The identity () static method creates an UnaryOperator object
  2. Using the apply() method, enter the string abc, and the result is also abc.
public class LambdaTest {
    public static void main(String[] args) {
        //Create an UnaryOperator object,
        UnaryOperator operator = UnaryOperator.identity();

        //Call the apply() method to output the value of the parameter
        System.out.println("The output is the same as the input:" + operator.apply("abc"));
    }
}
//Output results
 The output is the same as the input: abc

Parameters of the method used by UnaryOperator

Case requirements:

There is a list set of integers. Multiply each element in the set by 2, and then replace this element. The list set before and after replacement is output. There is a list set of strings, and each element in the set is replaced with its uppercase.

ArrayList Method description in
replaceAll(UnaryOperator operator) 
Replace each element in the list with the result of a unary operation function

Case steps:

  1. Use arrays Aslist() creates a list of integers
  2. Create UnaryOperator unary operation function and specify that the operation expression is x*2
  3. Call the replaceAll() method of ArrayList and pass the unary operation function created above as a parameter
  4. Output list before and after replacement
  5. Use arrays Aslist() creates a list of strings
  6. This time, the Lambda expression is directly passed in the replaceAll() method, s.toUpperCase()
  7. Output list before and after replacement
public class LambdaTest {
    public static void main(String[] args) {
        List<Integer> nums = Arrays.asList(3, 10, 8, 2);
        System.out.println("Before replacement:" + nums);
        UnaryOperator<Integer> oper = x -> x * 2;
        nums.replaceAll(oper);
        System.out.println("After replacement:" + nums);

        List<String> names = Arrays.asList("Jack","Rose","Tom","NewBoy");
        System.out.println("Before replacement:" + names);
        names.replaceAll(s -> s.toUpperCase());
        System.out.println("After replacement:" + names);
    }
}
//output
 Before replacement:[3, 10, 8, 2]
After replacement:[6, 20, 16, 4]
Before replacement:[Jack, Rose, Tom, NewBoy]
After replacement:[JACK, ROSE, TOM, NEWBOY]

7, Summary of common functional interfaces

(1) Supplier data provider

  1. T get(); There are no parameters passed in and there are results.

(2) Consumer consumer data

  1. void accept(T t); Incoming data, no results.  
  2. andThen()   

(3) Predicate predicate

  1. boolean test(T t); Logical judgment of incoming data
  2. and()
  3. or()
  4. negate()
  5. isEqual()

(4) Function function

  1. R apply(T t); Pass in a variable to return the calculation result
  2. andThen()
  3. compose()
  4. identity()

(5) BinaryOperator binary operator

  1. T apply(T t,T u); Pass in two parameters and return a result
  2. andThen()
  3. Inherited from BiFunction

(6)UnaryOperator

  1. Inherited from Function
  2. Unary operator
  3. T apply(T t); Pass in a parameter and return a result
  4. andThen()
  5. compose()
  6. identity()

reference resources:

Java 8 functional interface

https://www.runoob.com/java/java8-functional-interfaces.html

Dead knock functional interface - common functional interface

https://blog.csdn.net/heihaozi/article/details/104257942?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.control&spm=1001.2101.3001.4242

Common functional interfaces

https://blog.csdn.net/h294590501/article/details/80303693

Keywords: Java Lambda java8

Added by xepherys on Tue, 21 Dec 2021 07:47:14 +0200