Java smallholder cultivation record day 22

day22

Chapter I functional interface

1.1 concept

Functional interface in Java refers to an interface with only one abstract method.
Functional interface, that is, the interface suitable for functional programming scenarios. The embodiment of functional programming in Java is Lambda, so functional interface is the interface that can be used by Lambda. Only by ensuring that there is and only one abstract method in the interface can Lambda in Java be deduced smoothly.

Note: "syntax sugar" refers to the code syntax that is more convenient to use, but the principle remains the same. For example, when traversing a collection, the underlying implementation principle of the for each syntax is still the iterator, which is the "syntax sugar". From the application level, Lambda in Java can be regarded as the "syntax sugar" of anonymous internal classes, but they are different in principle.

1.2 format

Just make sure there is and only one abstract method in the interface

Modifier  interface Interface name{
	public abstract Return value type method name(Optional parameter information);
	//Other non abstract class methods: default method, static method and private method
}

Since the public abstract of the abstract method in the interface can be omitted, it is very simple to define a functional interface.

public interface MyFunctionalInterface{
	void myMethod();
}

1.3 @ functionlininterface annotation

  • @Functional interface - Java 8 began to support, identifying an anonymous function or functional interface.
  • @Override - checks whether the method is an override method. If it is found that its parent class or the referenced interface does not have this method, a compilation error will be reported.
/*
    Functional interface: an interface with only one abstract method is called functional interface
    Of course, the interface can contain other methods (black default, static, private)

    @FunctionalInterface annotation
    Function: it can detect whether the interface is a functional interface
        Yes: compilation succeeded
        No: compilation failed (there is no abstract method in the interface or the number of abstract methods is more than 1)

 */

@FunctionalInterface
public interface MyFunctionalInterface {
    //Define an abstract method
    public abstract void method();

}
/*
    @Override annotation
    Check whether the method is an overridden method
        Yes: compilation succeeded
        No: compilation failed
*/
public class MyFunctionalInterfaceImpl implements MyFunctionalInterface{
    @Override
    public void method() {

    }

}
/*
    Use of socket interface: generally, it can be used as the parameter and return value type of method
 */
public class Demo {
    //Define a method whose parameters use the functional interface MyFunctionalInterface
    public static void show(MyFunctionalInterface myInter){
        myInter.method();
    }

    public static void main(String[] args) {
        //Call the show method. The parameter of the method is an interface, so the implementation class object of the interface can be passed
        show(new MyFunctionalInterfaceImpl());

        //Call the show method. The parameter of the method is an interface, so we can pass the anonymous inner class of the interface
        show(new MyFunctionalInterface() {
            @Override
            public void method() {
                System.out.println("Overriding abstract methods in interfaces with anonymous inner classes");
            }
        });

        //Call the show method. The parameter of the method is a functional interface, so we can use Lambda expression
        show(()->{
            System.out.println("use Lambda Abstract methods in expression rewriting interface");
        });

        //Simplified Lambda expression
        show(()-> System.out.println("use Lambda Abstract methods in expression rewriting interface")
        );
    }
}

Chapter II functional programming

2.1 delayed execution of lambda

After the code of some scenarios is executed, the results may not be used, resulting in performance waste. Lambda expressions are delayed, which can be used as a solution to improve performance.

Log cases of performance waste

Note: logs can help us quickly locate problems and record the situation during the operation of the program, so as to facilitate the monitoring and optimization of the project.
A typical scenario is to conditionally use parameters. For example, after splicing log messages, print out when conditions are met:

/*
    Log case

    Some performance waste problems are found in the following code
    Call the showLog method, and the second parameter passed is a spliced string
    First splice the strings, and then call the showLog method
    showLog In the method, if the passed Bai Zhi level is not level 1
    Then it will not be such a spliced string
    Therefore, I feel that the string is spliced in white, which is a waste

 */
public class Demo01Logger {
    //Define a method to display log information according to the log level
    public static void showLog(int level, String message){
        //Judge the level of the log. If it is level 1, the log information will be output
        if (level == 1){
            System.out.println(message);
        }
    }

    public static void main(String[] args) {
        //Define three log information
        String msg1 = "Hello";
        String msg2 = "World";
        String msg3 = "Java";

        //Call showLog method to pass log level and log information
        showLog(1, msg1 + msg2 + msg3);
        showLog(2, msg1 + msg2 + msg3);
    }
}

Optimize log cases using Lambda

@FunctionalInterface
public interface MessageBuilder {
    //Define an abstract method for splicing messages and return the spliced information
    public abstract String builderMessage();
}
/*
    Optimize log cases using Lambda
    Lambda Features: delayed loading
    Lambda There must be a functional interface before using

 */
public class Demo02Lambda {
    //Define a method to display the log. The parameters of the method are the level of the delivery log and the MessageBuilder interface
    public static void showLog (int level, MessageBuilder mb){
        //Judge the level of the log. If it is level 1, call the builderMessage method in the MessageBuilder interface
        if (level == 1){
            System.out.println(mb.builderMessage());
        }
    }

    public static void main(String[] args) {
        //Define three log information
        String msg1 = "Hello";
        String msg2 = "World";
        String msg3 = "Java";

        //Call showLog method. The parameter MessageBuilder is a functional interface, so Lambda expression can be passed
        showLog(2,()->{
            //Returns a spliced string
            return msg1 + msg2 + msg3;
        });

        /*
        The Lambda expression is passed as a parameter, just passing the parameter to the showLog method
        Only if the conditions are met, the log level is level 1
            Will call the method builderMessage in the interface MessageBuilder
            String splicing will be carried out
        If the conditions are not met, Baizhi's level is not level 1
            Then the method builderMessage in the MessageBuilder interface will not be executed
            Therefore, the code for splicing strings will not be executed
        Therefore, there will be no waste of performance
         */
    }
}

2.2 use Lambda as parameter and return value

Regardless of the implementation principle, Lambda expressions in Java can be regarded as an alternative to anonymous inner classes. If the parameter of a method is a functional interface type, you can use a Lambda expression instead. Using Lambda expressions as method parameters is actually using functional interfaces as method parameters.
For example, Java Lang. Runnable interface is a functional interface. Assuming that a startThread method uses this interface as a parameter, you can use Lambda to pass parameters. In fact, this situation is not fundamentally different from the construction method parameter of Thread class, which is Runnable.

/*
    For example, Java Lang. runnable interface is a functional interface,
    Assuming that a startThread method uses this interface as a parameter, you can use Lambda to pass parameters.
    In fact, this situation is not fundamentally different from the construction method parameter of Thread class, which is Runnable.
 */
public class Demo01Runnable {
    //Define a method startThread. The parameters of the method use the functional interface Runnable
    public static void startThread(Runnable run){
        //Turn on Multithreading
        new Thread(run).start();

    }

    public static void main(String[] args) {
        //Call the startThread method. The parameter of the method is an interface. Then we can pass the anonymous inner class of this interface
        startThread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "-->" + "The thread started");
            }
        });
        //Call the startThread method. The parameter of the method is a functional interface, so you can pass a Lambda expression
        startThread(()->{
            System.out.println(Thread.currentThread().getName() + "-->" + "The thread started");
        });

        //Optimize Lambda expressions
        startThread(()->
            System.out.println(Thread.currentThread().getName() + "-->" + "The thread started")
        );
    }
}

Similarly, if the return value type of a method is a functional interface, you can directly return a Lambda expression. When you need a method to get a Java util. When an object of comparator interface type is used as a sorter, you can call this method to obtain it.

import java.util.Arrays;
import java.util.Comparator;

/*
    If the return value type of a method is a functional interface, you can directly return a Lambda expression.
    When you need a method to get a Java util. When an object of comparator interface type is used as a sorter, you can call this method to obtain it.
 */
public class Demo02Comparator {
    //Define a method whose return value type uses the function interface Comparator
    public static Comparator<String> getComparator(){
        /*
        //If the return value type of the method is an interface, we can return the anonymous inner class of this interface
        return new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //Sort in descending order of strings
                return o2.length() - o1.length();
            }
        };
        */
        /*
        //The return value type of method is a functional interface, so we can return a Lambda expression
        return (String o1, String o2) ->{
            //Sort in descending order of strings
            return o2.length() - o1.length();
        };
        */
        //Continue optimizing Lambda expressions
        return (o1, o2)->o2.length() - o1.length();
    }
    public static void main(String[] args){
        //Output array before sorting
        String[] arr = {"aaa", "b" , "cccccc", "dddddddddd"};
        //Output array before sorting
        System.out.println(Arrays.toString(arr));//[aaa, b, cccccc, dddddddddd]
        //Call the sort method in Arrays to sort the string array
        Arrays.sort(arr, getComparator());
        //Output sorted array
        System.out.println(Arrays.toString(arr));//[dddddddddd, cccccc, aaa, b]
    }
}

Chapter III common functional interfaces

JDK provides a large number of commonly used functional interfaces to enrich the typical usage scenarios of Lambda, which are mainly in Java util. Function package. The following are the simplest interfaces and use examples.

3.1 Supplier interface

java. util. function. The supplier < T > interface contains only one parameterless method: T get(). Used to obtain object data of the type specified by a generic parameter. Because this is a functional interface, it means that the corresponding Lambda expression needs to "provide" an object data conforming to the generic type.

import java.util.function.Supplier;

/*
    Common functional interfaces
    java.util.function.Supplier<T>The interface contains only one parameterless method: T get(). Used to obtain object data of the type specified by a generic parameter.

    Supplier<T>An interface is called a production interface. It specifies what type of generic interface is and what type of data the get method in the interface will produce
 */
public class Demo01Supplier {
    //Define a method, pass the parameters of the method to the supplier < T > interface, generically execute String, and the get method will return a String
    public static String getString(Supplier<String> sup){
        return sup.get();
    }

    public static void main(String[] args) {
        //Call the getString method. The parameter Supplier of the method is a functional interface, so you can pass a Lambda expression
        String s = getString(()->{
            return "Hu Ge";
        });

        System.out.println(s);

        //Optimize Lambda expressions
        String s2 = getString(()->"Hu Ge");
        System.out.println(s2);
    }
}

3.2 exercise: find the maximum value of array elements

subject
Using the supplier interface as the method parameter type, find the maximum value in the int array through the Lambda expression. Tip: please use Java for the generic type of interface Lang. integer class.

import java.util.function.Supplier;

/*
    Exercise: maximizing array elements
    Using the Supplier interface as the method parameter type, find the maximum value in the int array through the Lambda expression.
    Tip: please use Java. Com for interface generics Lang. integer class.
 */
public class Demo02Test {
    //Define a method to obtain the maximum value of the element in the int type array. The parameters of the method are passed to the Supplier interface. The generics use Integer
    public static int getMax(Supplier<Integer> sup){
        return sup.get();
    }

    public static void main(String[] args) {
        //Define an array of type int and assign a value
        int[] arr = {100, 1, -50, 88, 99};
        //Call the getMax method. The parameter Supplier of the method is a functional interface, so you can pass a Lambda expression
        int maxValue = getMax(()->{
            //Gets the maximum value of the array and returns
            //Define a variable, assign the first element in the array to the variable, and record the maximum value of the element in the array
            int max = arr[0];
            //Traverse the array to get other elements in the array
            for (int i : arr){
                //Use other elements to compare with the maximum
                if (i > max){
                    //If i is greater than max, replace Max as the maximum value
                    max = i;
                }
            }
            //Returns the maximum value
            return max;
        });

        System.out.println("The maximum value is:" + maxValue);
    }
}

3.3 consner interface

java. util. function. The consumer < T > interface is just opposite to the Supplier interface. Instead of producing a data, it consumes a data, and its data type is determined by generics.

Abstract method: accept

The Consumer interface contains the abstract method void accept (T), which means to consume data of a specified generic type. Basic use, such as:

import java.util.function.Consumer;

/*
    java.util.function.Consumer<T>The interface is just opposite to the supplier interface,
        It does not produce a data, but consumes a data, and its data type is determined by generics.
    Consumer The interface contains the abstract method void accept (T), which means to consume data of a specified generic type.

    Consumer Interface is a consumer interface. You can use the accept method to consume data of any type according to the type of generic execution
    As for how to consume (use), you need to customize (output, calculation...)

 */
public class Demo01Consumer {
    /*
        Define a method
        Method passes the name of a string
        The parameters of the method are passed to the Consumer interface, and the generic type uses String
        You can use the Consumer interface to consume the name of the string
     */
    public static void method(String name, Consumer<String> con){
        con.accept(name);
    }

    public static void main(String[] args) {
        //Call the method method to pass the string name. Another parameter of the method is the Consumer interface, which is a functional interface, so you can pass a Lambda expression
        method("Zhao Liying" , (String name)->{
            //Consume the passed string
            //Consumption mode: direct output string
            System.out.println(name);

            //Consumption mode: invert the string to output
            String reName = new StringBuffer(name).reverse().toString();
            System.out.println(reName);
        });
    }
}

Default method: andThen

If the parameters and return values of a method are all of consumer type, the effect can be achieved: when consuming data, first do an operation, and then do an operation to realize combination. This method is the default method andThen in the consumer interface. The following is the source code of JDK:

	default consumer<T> andThen(Consumer<? super T> after) {
		Objects.requireNonNull(after) ;
		return (T t) -> { accept(t); after.accept(t); };
	}

Note: Java util. The requineNonNull static method of objects will actively throw a NullPointerException exception when the parameter is null. This eliminates the trouble of repeatedly writing if statements and throwing null pointer exceptions.

To realize composition, you need two or more Lambda expressions, and the semantics of andThen is "step by step". For example, when two steps are combined:

import java.util.function.Consumer;

/*

    Consumer The default method of the interface andThen
    Function: two Consumer interfaces are required. The two Consumer interfaces can be combined to consume data

    For example:
        Consumer<String> con1
        Consumer<String> con2
        String s = "hello";
        con1.accept(s);
        con2.accept(s);
        Connect two Consumer interfaces before consumption
        con1.andThen(con2).accept(s);Who writes first, who consumes first
 */
public class Demo02AndThen {
    //Define a method. The parameters of the method pass a string and two Consumer interfaces. The generics of the Consumer interface use a string
    public static void method(String s, Consumer<String> con1, Consumer<String> con2){
        //con1.accept(s);
        //con2.accept(s);

        //Use the andThen method to connect the two Consumer interfaces together to consume data
        con1.andThen(con2).accept(s);
    }

    public static void main(String[] args) {
        //Call method to pass a string and two Lambda expressions
        method("Hello", (t)->{
            //Consumption mode: convert the string to uppercase output
            System.out.println(t.toUpperCase());
        },(t)->{
            //Consumption mode: convert the string to lowercase output
            System.out.println(t.toLowerCase());
        });
    }
}

3.4 exercise: formatting and printing information

subject
There are multiple pieces of information in the following string array. Please print the information in the format of "" Name: xx. Gender: xx "". It is required to take the action of printing the name as the Lambda instance of the first Consumer interface, take the action of printing the gender as the Lambda instance of the second Consumer interface, and "splice" the two Consumer interfaces together in order.

import java.util.function.Consumer;

/*
    practice:
    There are multiple pieces of information in the string array. Please follow the format "Name: Xx. Gender: Xx." Print the information in the format of.
    It is required to print the name as the Lambda instance of the first Consumer interface,
    Take the action of printing gender as the Lambda instance of the second Consumer interface,
    Splice the two Consumer interfaces together in order.
 */
public class Demo03Test {
    //Define a method, pass String type, array and two Consumer interfaces for parameters, and use String for generics
    public static void printInfo(String[] arr, Consumer<String> con1, Consumer<String> con2){
        //Traversal string array
        for (String message : arr){
            //Use the andThen method to connect two Consumer interfaces to consume strings
            con1.andThen(con2).accept(message);
            System.out.println();
        }
    }

    public static void main(String[] args) {
        //Defines an array of string types
        String[] arr = {"Delireba,female", "Gulinaza,female", "Marzaha,male"};
        //Call the printInfo method to pass a string array and two Lambda expressions
        printInfo(arr, (message)->{
            //Consumption mode: cut the message, get the name, and output it in the specified format
            String name = message.split(",")[0];
            System.out.print("full name:" + name);
        }, (message)->{
            //Consumption mode: cut the message, get the age, and output it in the specified format
            String age = message.split(",")[1];
            System.out.print(". Age:" + age + ". ");
        });
    }
}

3.5 predict interface

Sometimes we need to judge some type of data to get a boolean value result. You can use Java util. function . Predict < T > interface.

Abstract method: test

The predict interface contains an abstract method: Boolean test (T). Scenarios for condition judgment:

import java.util.function.Predicate;

/*
    java.util.function . Predicate<T>Interface
    Function: judge the data of a certain data type, and the result returns a boolean value
        Predicate The interface contains an abstract method:
            boolean test( T t):A method used to judge data of a specified data type
                result:
                    If the conditions are met, return true
                    If the conditions are not met, false is returned

 */
public class Demo01Predicate {
    /*
        Define a method
        Parameter passes a String of type String
        Pass a Predicate interface, and the generic type uses String
        Use the method test in predict to judge the string and return the judgment result
     */
    public static boolean checkString(String s, Predicate<String> pre){
        return pre.test(s);
    }

    public static void main(String[] args) {
        //Define a string
        String s = "abcdef";

        //Call the checkString method to verify the string, and pass the string and Lambda expression as parameters
        boolean b = checkString(s, (str)->{
            //Judge the string passed by the parameter, judge whether the length of the string is greater than 5, and return the judgment result
           return str.length() > 5;
        });
        System.out.println(b);
    }
}

The criterion of condition judgment is the incoming Lambda expression logic. As long as the string length is greater than 5, it is considered to be very long

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 logically connected by "and" to achieve the effect of "and". Its JDK source code is:

default Predicate<T> and(Predicate< ? super T> other) {
	Objects.requireNonNull(other);
	return (t) -> test(t) && other.test(t);
}
import java.util.function.Predicate;

/*
    Logical expression: conditions that can connect multiple judgments
    &&:And operator, false if false
    ||:Or operator, true if true
    !:Non (negative) operator, false if not true, true if not false

    Requirement: there are two conditions for judging a string
        1.Judge whether the length of the string is greater than 5
        2.Judge whether the string contains a
    If the two conditions must be met at the same time, we can use the & & operator to connect the two conditions

    Predicate There is a method and in the interface, which represents the relationship and can also be used to connect two judgment conditions
    default Predicate<T> and (Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t)-> this.test(t) && other.test(t);
    }

    The two judgment conditions inside the method are also connected by using the & & operator
 */
public class Demo02Predicate_and {
    /*
        Define a method, parameters of the method, and pass a string
        Pass two Predicate interfaces
            One used to judge whether the length of the string is greater than 5
            A used to determine whether the string contains a
            Two conditions must be met
     */
    public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2){
        //return pre1.test(s) && pre2.test(s);
        return pre1.and(pre2).test(s);
    }

    public static void main(String[] args) {
        //Define a string
        String s = "abcdef";
        //Call the checkstring method and pass the string and two Lambda expressions as parameters
        boolean b = checkString(s, (String str)->{
           //Judge whether the length of the string is greater than 5
           return str.length() > 5;
        },(String str)->{
            //Judge whether the string contains a
            return str.contains("a");
        });
        System.out.println(b);
    }
}

Default method: or

Similar to the "and" of and, the default method or implements the "or" in the logical relationship. The JDK source code is:

	default Predicate<T> or(Predicate< ? super T> other) {
		Objects.requireNonNull(other);
		return (t) -> test(t) ll other.tlest(t);
	}
import java.util.function.Predicate;

/*
    Requirement: there are two conditions for judging a string
        1.Judge whether the length of the string is greater than 5
        2.Judge whether the string contains a
    If one condition is satisfied, we can use the | operator to connect two conditions

    Predicate There is a method or in the interface, which represents or relationship, and can also be used to connect two judgment conditions
    default Predicate<T> or ( Predicate<? super T> other) {
        Objects.requireNonNull (other );
        return (t) -> test(t) || other.test(t);
    }
    The two judgment conditions inside the method are also connected by the | operator

 */
public class Demo03Predicate_or {
    /*
        Define a method, parameters of the method, and pass a string
        Pass two Predicate interfaces
            One used to judge whether the length of the string is greater than 5
            A used to determine whether the string contains a
            Just meet one condition
     */
    public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2){
        //return pre1.test(s) || pre2.test(s);
        return pre1.or(pre2).test(s);
    }

    public static void main(String[] args) {
        //Define a string
        String s = "bbcdef";
        //Call the checkstring method and pass the string and two Lambda expressions as parameters
        boolean b = checkString(s, (String str)->{
            //Judge whether the length of the string is greater than 5
            return str.length() > 5;
        },(String str)->{
            //Judge whether the string contains a
            return str.contains("a");
        });
        System.out.println(b);
    }
}

Default method: negate

"And", "or" have been understood, and the remaining "non" (negative) will be simple. The JDK source code of the default method negate is:

	default Predicate<T> negate() {
		return (t) -> !test(t);
	}
import java.util.function.Predicate;

/*
    Requirement: judge whether the length of a string is greater than 5
        If the length of the string is greater than 5, false is returned
        Returns true if the length of the string is not greater than 5
    So we can use the inverse symbol! Reverse the judgment result

    Predicate There is a method negate in the interface, which also means negate
    default Predicate<T> negate( ) {
        return (t) -> !test(t);
    }

 */
public class Demo04Predicate_negate {
    /*
        Define a method, parameters of the method, and pass a string
        Use the predict interface to judge whether the length of the string is greater than 5

     */
    public static boolean checkString(String s, Predicate<String> pre){
        //return !pre.test(s);
        return pre.negate().test(s);
    }
    public static void main(String[] args) {
        String s = "abc";
        boolean b = checkString(s, (String str)->{
           return str.length() > 5;
        });
        System.out.println(b);
    }
}

3.6 exercise: collection information filtering

subject
There are multiple "name + gender" information in the array as follows. Please filter the qualified strings into the set ArrayList through the assembly of the Predicate interface. Two conditions need to be met at the same time:

  1. Must be female;
  2. The name is 4 words.
import java.util.ArrayList;
import java.util.function.Predicate;

/*
    Exercise: collection information filtering
    There are multiple pieces of "name + gender" information in the array as follows,
    String[] array = {"Diri Reba, female "," gulinaza, female "," marzaha, male "," Zhao Liying, female "};
    Please filter the qualified strings into the collection ArrayList through the assembly of predict interface,
    Two conditions need to be met at the same time:
        1.Must be female;
        2.The name is 4 words.

    analysis:
        1.There are two judgment conditions, so you need to use two predict interfaces to judge the conditions
        2.The two conditions must be met at the same time, so you can use the and method to connect the two judgment conditions

 */
public class Demo05Test {
    /*
    Define a method
    Method passes an array containing personnel information
    Pass two Predicate interfaces to filter the information in the array
    Save the information that meets the conditions into the ArrayList set and return it
     */
    public static ArrayList<String> filter(String[] arr, Predicate<String> pre1, Predicate<String> pre2){
        //Define an ArrayList collection to store the filtered information
        ArrayList<String> list = new ArrayList<>();
        //Traverse the array and get each piece of information in the array
        for(String s : arr){
            //Use the test method in the predict interface to judge the obtained string
            boolean b = pre1.and(pre2).test(s);
            //Judge the Boolean value obtained
            if(b){
                //If the condition holds, both conditions are met, and the information is stored in the ArrayList set
                list.add(s);
            }
        }
        //Return the set
        return list;
    }

    public static void main(String[] args) {
        //Defines an array of stored strings
        String[] array = {"Delireba,female","Gulinaza,female","Marzaha,male","Zhao Liying,female"};
        //Call the filter method to pass a string array and two Lambda expressions
        ArrayList<String> list = filter(array,(String s)->{
            //Get the gender in the string and judge whether it is female
            return s.split(",")[1].equals("female");
        },(String s)->{
            //Get the name in the string and judge whether the length is 4 characters
            return s.split(",")[0].length() == 4;
        });
        //Traversal set
        for(String str : list){
            System.out.println(str);
        }
    }
}

3.7 Function interface

java. util. function. The function < T, R > interface is used to obtain another type of data from one type of data. The former is called pre condition and the latter is called post condition.

Note that the pre condition generics and post condition generics of a Function can be the same

Abstract method: apply

The main abstract method in the Function interface is R apply(T t), which obtains the result of type R according to the parameters of type T. For example, convert String type to Integer type.

import java.util.function.Function;

/*
    java.util.function. Function<T,R>The interface is used to obtain data of another type according to data of one type,
        The former is called pre condition and the latter is called post condition.
    Function The main abstract method in the interface is R apply(T t), which obtains the result of type R according to the parameters of type T.
        Use scenarios such as converting string type to Integer type.

 */
public class Demo01Function {
    /*
        Define a method
        Method passes an integer of type string
        The parameters of the method are passed to a Function interface, and the generic type uses < string, integer >
        Use the method apply in the Function interface to convert an Integer of string type into an Integer of Integer type
     */
    public static void change(String s, Function<String, Integer> fun){
        //Integer in = fun.apply(s);
        int in = fun.apply(s);//Automatic unpacking integer - > int
        System.out.println(in);
    }

    public static void main(String[] args) {
        //Defines an integer of type string
        String s = "1234";
        //Call the change method to pass an integer of string type and a Lambda expression
        change(s, (String str)->{
            //Converts an Integer of string type to an Integer of Integer type and returns
            return Integer.parseInt(str);
        });
    }
}

Default method: andThen

There is a default andThen method in the Function interface, which is used for combination operations. JDK source code is as follows:

	default <v> Function<T,V> andThen(Function<? super R, ? extends V> after) {
		Objects.requireNonNull(after) ;
		return (T t) -> after.apply( apply(t) );
	}

This method is also used in the "do what first, then do what" scenario, which is similar to andThen in Consumer:

import java.util.function.Function;

/*
    Function Black recognition method andThen in the interface: used for combination operation

    Requirements:
        Convert "123" of string type to Integer type, and add 10 to the converted result
        Convert the added Integer type data to String type

    analysis:
        Converted twice
        The first time is to convert String type to Integer type
            So we can use function < string, integer > fun1
                Integer i =fun1.apply("123")+10;
        The second is to convert Integer type to string type
            So we can use function < integer, string > fun2
                String s = fun2.apply(i);
        We can use the andThen method to combine the two transformations together
            String s = fun1.andThen(fun2 ).apply( "123"");
            fun1 First call the apply method to convert the string to Integer
            fun2 Then call the appLy method to convert Integer into string

 */
public class Demo02Function_andThen {
    /*
        Define a method
        Parameter string an integer of string type
        Parameters are passed to two Function interfaces
            A generic type uses function < string, integer >
            A generic type uses function < integer, string >
     */
    public static void change(String s, Function<String, Integer> fun1, Function<Integer, String> fun2){
        String ss = fun1.andThen(fun2).apply(s);
        System.out.println(ss);
    }

    public static void main(String[] args) {
        //Defines an integer of type string
        String s = "123";
        //Call the change method, passing a string and two Lambda expressions
        change(s, (String str)->{
            //Convert string to integer + 10
            return Integer.parseInt(str) + 10;
        },(Integer i)->{
            //Convert an integer to a string
            return i + "";
        });
    }
}

3.8 exercise: user defined function model splicing

subject
Please use Function to splice Function models. Multiple Function operations to be performed in order are:

String str ="Zhao Liying,20"";
  1. Intercepting the digital age part of the string to obtain the string;
  2. Convert the string in the previous step into a number of type int;
  3. Add up the int number of the previous step by 100 to get the result int number.
import java.util.function.Function;

/*
    Exercise: custom function model splicing
    subject
    Please use Function to splice Function models. Multiple Function operations to be performed in order are:
        String str ="Zhao Liying, 20 ";
    analysis;
        1.Intercepting the digital age part of the string to obtain the string;
            Function<String, String>"Zhao Liying, 20 "- >" 20“
        2.Convert the string in the previous step into a number of type int;
            Function<String,Integer> "20"->20
        3.Add up the int number of the previous step by 100 to get the result int number.
            Function<Integer, Integer> 20->120
 */
public class Demo03Test {
    /*
        Define a method
        Parameter passes a string containing the name and age
        Parameter and then pass three Function interfaces for type conversion
     */
    public static int change(String s, Function<String, String> fun1,
                             Function<String, Integer> fun2, Function<Integer, Integer> fun3){
        //Combine the three transformations using the andThen method
        return fun1.andThen(fun2).andThen(fun3).apply(s);
    }

    public static void main(String[] args) {
        String str = "Zhao Liying,20";

        int num = change(str, (String s)->{
            //"Zhao Liying, 20" - > "20"
            return s.split(",")[1];
        }, (String s)->{
            //"20"->20
            return Integer.parseInt(s);
        }, (Integer i)->{
            //20->120
            return i + 100;
        });
        System.out.println(num);
    }
}

Keywords: Java Back-end

Added by littledragon on Wed, 26 Jan 2022 20:44:57 +0200