Chapter 1 functional interface
1.1 the concept of functional interface & the definition of functional interface
- In Java, functional interface refers to an interface with only one abstract method.
-
Syntax sugar refers to the code syntax which is more convenient to use but the principle is unchanged.
- For each is the syntax sugar of the iterator.
- From the application layer: Lambda can be used as the syntax sugar of anonymous inner class
- But the two principles are different.
- Anonymous inner classes generate. class files ($named), but Lambda does not
- So Lambda is efficient
- Note: functional interface: an interface with only one abstract method is called functional interface
- Of course, the interface can contain other methods (default, static, private)
1.2 format of functional interface
1.3 @ functional interface annotation of functional interface
- @Functional interface annotation - > write functional interface in the future
- Function: can detect whether the interface is a functional interface
- Yes: compilation succeeded
- No: compilation failed (there are more than one abstract method without abstract method in the interface)
- Function: can detect whether the interface is a functional interface
1.4 use of functional interface
- Use of functional interface: generally, it can be used as the parameter and return value type of the method
Chapter II functional programming
2.1 delayed execution of lambda
2.1.1 log cases of performance waste
- Journal:
- It can help us quickly locate problems and record the process of program running, so as to monitor and optimize the project
- Log case
- Some performance waste problems found in the following code [!]
- Call the showLog method. The second parameter passed is a concatenated string
- First, splice the strings, and then call the showLog method
- If the log level passed in the showLog method is not level 1
- Then it won't be such a concatenated string
- So it feels like strings are white spliced, and there is waste
public class Demo01Logger { //Define a method to display log information based on the level of the log 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 the showLog method to pass the log level and log information showLog(1, msg1 + msg2 + msg3); } } //Result: HelloWorldJava
2.1.2 use Lambda to optimize log cases
- Optimizing log cases with Lambda
- Lambda features: delayed loading [!]
- The premise of Lambda is that there must be a functional interface [!]
-
Use Lambda expression to pass as parameter, just pass the parameter to showLog method
- Only if the conditions are met, the log level is level 1
- Will call the method buildmessage in the interface MessageBuilder
- String splicing
-
If the conditions are not met, the log level is not level 1
- Then the method buildmessage in the MessageBuilder interface will not execute
- So the concatenated string code will not execute either
- So there's no performance waste
- Only if the conditions are met, the log level is level 1
//Defined functional interface: MessageBuilder.java @FunctionalInterface public interface MessageBuilder { //Define an abstract method for splicing messages, and return the spliced information public abstract String builderMessage(); } //Main method: Demo02Lambda.java public class Demo02Lambda { //Define a method to display the log, the level of the method's parameter 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 buildmessage 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 the showLog method. The parameter MessageBuilder is a functional interface, so you can pass Lambda expressions showLog(1, () -> { System.out.println("Do not execute if the conditions are not met"); //Returns a concatenated string return msg1 + msg2 + msg3; }); } } //Results: (when satisfied) //Do not execute if the conditions are not met HelloWorldJava //Result: (not satisfied)
2.2 functional interface as the parameter of method case
/* For example, the java.lang.Runnable interface is a functional interface, If you have a startThread method that uses this interface as a parameter, you can use Lambda to pass parameters. In fact, there is no essential difference between this situation and the Thread class's constructor parameter of Runnable. */ public class Demo01Runnable { //Define a method startThread. The parameters of the method use the function 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 the interface startThread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName() + "-->" + "Thread started"); //currentThread() currently executing thread } }); //Call the startThread method. The parameter of the method is a functional interface, so you can pass the Lambda expression startThread(() -> { System.out.println(Thread.currentThread().getName() + "-->" + "Thread started"); //currentThread() currently executing thread }); //Optimizing Lambda startThread(() -> System.out.println(Thread.currentThread().getName() + "-->" + "Thread started")); } } //Result: Thread-0-->Thread started Thread-1-->Thread started Thread-2-->Thread started
2.3 case of function interface as return value type of method
/* If the return value type of a method is a functional interface, a Lambda expression can be returned directly. When you need to obtain an object of java.util.Comparator interface type as a sorter through a method, you can call this method to obtain. */ public class Demo02Comparator { //Define a method whose return value type uses the function interface Comparator public static Comparator<String> getComparator(){ //The return value type of method is an interface, so we can return the anonymous inner class of this interface /*return new Comparator<String>() { @Override public int compare(String o1, String o2) { //Sort strings in descending order return o2.length()-o1.length(); } };*/ //The return value type of the method is a functional interface, so we can return a Lambda expression /*return (String o1, String o2) -> { return o2.length()-o1.length(); };*/ //Continue to optimize Lambda return (o1, o2) -> o2.length()-o1.length(); } //Main function public static void main(String[] args) { //Create an array of strings String[] arr = {"aaa", "bb", "cccccc", "ddddddddddd"}; //Output string before sorting System.out.println(Arrays.toString(arr)); //[aaa, bb, cccccc, ddddddddddd] //Call the sort method in Arrays to sort the string array Arrays.sort(arr, getComparator()); //Output sorted string System.out.println(Arrays.toString(arr)); //[ddddddddddd, cccccc, aaa, bb] } } //Result: [aaa, bb, cccccc, ddddddddddd] [ddddddddddd, cccccc, aaa, bb]
Chapter 3 common functional interfaces
3.1 common functional interface (supplier interface)
- The java.util.function.Supplier interface contains only one method without parameters
- T get(). Used to get object data of the type specified by a generic parameter.
- The Supplier interface is called a production interface. If you specify the generic type of the interface, the get method in the interface will produce the data of what type
- Produce a data
public class Demo01Supplier { //Define a method. The parameter of the method passes the supplier < T > interface. If the generic type executes String, 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 the Lambda expression String s = getString(() -> { //Produce a string and return return "Hu Ge"; }); System.out.println(s); //Optimizing Lambda String s2 = getString(() -> "Google"); System.out.println(s2); } } //Result: //Hu Ge //Google
3.2 Supplier interface exercise - finding the maximum value of array elements
public class Demo02Test { //Define a method to get the maximum value of the elements in the array of type int, pass the Supplier interface for the parameters of the method, and use Integer for generics public static int getMax(Supplier<Integer> sup){ return sup.get(); } public static void main(String[] args) { //Define an array of type int and assign int[] arr = {100, 22, -33, 88, 40, 0}; //Call the getMax method. The parameter Supplier of the method is a functional interface, so you can pass the 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) { //Compare with maximum using other elements if (i > max) { //If i is greater than max, replace Max as the maximum max = i; } } return max; }); System.out.println("The largest elements in the array are:" + maxValue); } } //Result: //The largest element in the array is: 100
3.3 common functional interface (Consumer interface)
- The java.util.function.Consumer interface is the opposite of the Supplier interface,
- Instead of producing a data, it consumes a data whose data type is determined by generics.
- The Consumer interface contains the abstract method void accept (t t t), which means to consume data of a specified generic type.
- The Consumer interface is a Consumer interface. You can use the accept method to consume data of whatever type the generic implementation type is
- As for how to consume (use), you need to customize (output, calculate )
- Note: no return value
public class Demo01Consumer { /* Define a method Method to pass the name of a string The parameter of the method passes the Consumer interface, and the generic uses String Names that can consume strings using the Consumer interface */ public static void method(String name, Consumer<String> con){ con.accept(name); } public static void main(String[] args) { //Call the method method method and pass the string name. The other parameter of the method is the Consumer interface, which is a functional interface, so you can pass the Lambda expression method("Zhao Liying", (String name) -> { //Consume the passed string //Consumption mode: direct output //System.out.println(name); / / Zhao Liying //Consumption pattern: reversal String reName = new StringBuilder(name).reverse().toString(); //Chain programming System.out.println(reName); }); } } //Result: //Ying Li Zhao
3.4 default method of consumer interface andThen
- The default method of the Consumer interface andThen
- Function: two Consumer interfaces are required, which can be combined to consume data
- Note: multiple interfaces can also be connected together
con1.andThen(con2).andThen(con3).accept(s);
- For example:
Consumer<String> con1 Consumer<String> con2 String s = "hello"; con1.accept(s); con2.accept(s); Connect two Consumer interfaces for consumption con1.andThen(con2).accept(s); who writes first and who consumes first
- Note: who writes first and 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 strings public static void method(String s, Consumer<String> con1, Consumer<String> con2){ //Use common methods first //con1.accept(s); //con2.accept(s); //Use the default method andThen in the interface //Connect two Consumer interfaces for consumption con1.andThen(con2).accept(s); //Who writes first and who consumes first } public static void main(String[] args) { //Call method method, pass a string, two Lambda expressions method("Hello", (s) -> { //Consumption method, converting string to uppercase output System.out.println(s.toUpperCase()); }, (s) -> { //Consumer method, converting string to lowercase output System.out.println(s.toLowerCase()); }); } } //Result: HELLO hello
3.5 Consumer interface exercise string splicing output
public class Demo03Test { //Define a method to pass an array of String type and two consumer interfaces. Generics use String public static void printInfo(String[] arr, Consumer<String> con1, Consumer<String> con2){ //Traversal string array for (String message : arr) { //Using the andThen method to connect two Consumer interfaces, consuming strings con1.andThen(con2).accept(message); } } public static void main(String[] args) { //Define an array of string types String[] arr = {"Di Ali Gerba,female", "Guli Nazha,female", "Mar Zaha,male"}; //Call the printInfo method, passing an array of strings and two Lambda expressions printInfo(arr, (message) -> { //Consumption mode: cut message, get name and output in specified format String name = message.split(",")[0]; //String array index 0 saved name System.out.print("Full name:" + name); }, (message) -> { //Consumption mode: cut message, get gender, and output according to the specified format String sex = message.split(",")[1]; //Gender of string array index 1 System.out.println(",Full name:" + sex + ". "); }); } } //Result: //Name: delireba, name: female. //Name: gulinaza, name: female. //Name: malzaha, name: male.
3.6 common functional interface (Predicate) interface
- java.util.function.Predicate interface
- Function: judge the data of a data type and return a boolean value
- Can't store to collection, need customization - > just a judgment
- Return value
- The Predicate interface contains an abstract method, test:
- boolean test(T t): the method used to judge the data of the specified data type
- Result:
- Qualified, return true
- If the condition is not met, return false
- Result:
- boolean test(T t): the method used to judge the data of the specified data type
public class Demo01Predicate { /* Define a method Parameter to pass a String of type String Pass a Predicate interface, generic uses String Use the method test in Predicate to judge the string and return the 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 = "abcde"; //Call the checkString method to verify the string, and pass the string and Lambda expression /*boolean b = checkString(s, (String str) -> { //Judge the string passed by the parameter, judge whether the length of the string is greater than 5, and return the result return str.length() > 5; });*/ //Optimize Lambda expressions boolean b = checkString(s, str -> str.length() > 5); System.out.println(b); } } //Result: false
3.7 predict interface: the three default methods
- Logical expression: conditions that can connect multiple judgments
- &&: and operator, false if false
- ||: or operator, true if true
- !: non (negate) operator, false if not true, true if not false
- There is a method and in the Predicate interface to represent and relate, which can also be used to connect two judging conditions
default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> this.test(t) && other.test(t); }
- The two inner judgment conditions of the method are also connected by the & & operator
- Exercise requirements: judge a string, with two conditions
- Determine whether the length of the string is greater than 5
- Determine 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
public class Demo02Predicate_and { /* Define a method, parameters of the method, pass a string Pass two Predicate interfaces One is used to determine whether the length of the string is greater than 5 A is used to determine whether the string contains a Both conditions must be met at the same time */ public static boolean checkString(String s, Predicate<String> pre1, Predicate<String> pre2){ return pre1.and(pre2).test(s); //Equivalent to return pre1.test (s) & & pre2.test (s); } public static void main(String[] args) { //Define a string String s = "abcdef"; //Call checkString method, pass string and two Lambda expressions boolean b = checkString(s, (String str) -> { //Determine whether the length of the string is greater than 5 return str.length() > 5; }, (String str) -> { //Determine whether the string contains a return str.contains("a"); }); System.out.println(b); } } //Result: true
3.8 predict interface, one of the three default methods
- The Predicate interface has a method or, representation or relationship, which 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 inner judgment conditions of the method are also connected by the | | - operator
- Exercise: requirement: judge a string with two conditions
- Determine whether the length of the string is greater than 5
- Determine whether the string contains a
- If one condition is satisfied, we can use the 𞓜 operator to connect the two conditions
public class Demo03Predicate_or { /* Define a method, parameters of the method, pass a string Pass two Predicate interfaces One is used to determine whether the length of the string is greater than 5 A is used to determine whether the string contains a One condition is satisfied */ 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);//Equivalent to return pre1.test (s) | pre2.test (s); } public static void main(String[] args) { //Define a string String s = "bcgggg"; //Call checkString method, pass string and two Lambda expressions boolean b = checkString(s,(String str)->{ //Determine whether the length of the string is greater than 5 return str.length()>5; },(String str)->{ //Determine whether the string contains a return str.contains("a"); }); System.out.println(b); } } //Result: true
3.9 predict interface & negate (negative) of the three default methods
- There is a method "negate" in the Predicate interface, which also means "negate"
default Predicate<T> negate() { return (t) -> !test(t); }
- Exercise requirement: judge whether the length of a string is greater than 5
1. If the length of the string is greater than 5, return false
2. Return true if the length of string is not greater than 5
*So we can use the reverse sign to reverse the result of judgment
public class Demo04Predicate_negate { /* Define a method, parameters of the method, pass a string Use the Predicate interface to determine if the length of a string is greater than 5 */ public static boolean checkString(String s, Predicate<String> pre){ return pre.negate().test(s); //Equivalent to return! Pre.test (s); } public static void main(String[] args) { //Define a string String s = "abc"; //Call checkString method, pass string and Lambda expression /*boolean b = checkString(s, (String str) -> { return str.length() > 5; });*/ //Optimizing Lambda boolean b = checkString(s, str -> str.length() > 5); System.out.println(b); } } //Result: true
3.10 predict interface exercise set information filtering
public class Demo05Test { /* Define a method Method to pass an array of personnel information Pass two predict interfaces to filter the information in the array Store the information that meets the conditions in the ArrayList collection and return */ public static ArrayList<String> filter(String[] arr, Predicate<String> pre1, Predicate<String> pre2){ //Define an ArrayList collection to store filtered information ArrayList<String> listA = new ArrayList<>(); //Traverse the array to get every piece of information in the array for (String s : arr) { //It's arr, not listA //Use the method test in the Predicate interface to judge the obtained string boolean b = pre1.and(pre2).test(s); //Judge the obtained boolean value if(b){ //If the conditions are met, store the information in the ArrayList set listA.add(s); } } //Return the set return listA; } public static void main(String[] args) { //Define an array to store strings String[] array = { "Di Ali Gerba,female", "Guli Nazha,female", "Mar Zaha,male", "Zhao Liying,female" }; //Call the filter method, passing the string array and two Lambda expressions ArrayList<String> listA = filter(array, (String str) -> { //Must be a girl return str.split(",")[1].equals("female"); }, (String str) -> { //The name is 4 words. return str.split(",")[0].length()==4; }); //Ergodic set for (String s : listA) { System.out.println(s); } } } //Result: //Delireba, female //Gulinaza, female
3.11 common Function interface
- Java. Util. Function. Function < T, R >: interface is used to get data of one type from data of another type
- The former is called pre condition, and the latter is called post condition.
- The main abstract method in Function interface is: R apply (t t t): get the result of type R according to the parameter of type T.
- Exercise: use a scenario such as converting a String type to an Integer type.
public class Demo01Function { /* Define a method Method to pass an integer of type string The parameter of the method passes 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 to an Integer of Integer type */ public static void change(String s, Function<String, Integer> fun){ Integer in = fun.apply(s); //Can also be written as int, auto unpacking integer - > int System.out.println(in); } public static void main(String[] args) { //Define an integer of type string String s = "1234"; //Call the change method, pass the integer of string type, and Lambda expression /*change(s, (String str) -> { //Converts an Integer of type string to an Integer of type Integer return Integer.parseInt(str); });*/ //Optimizing Lambda change(s, str -> Integer.parseInt(str)); } } //Result: (Integer type) 1234
3.12 Function interface default method and then
- The default method andThen: in Function interface is used for combination operation
- Demand:
- Convert "123" of String type to Inteter type, and add 10 to the converted result
- Convert the data of Integer type after adding to String type
- Analysis:
- Changed 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;
- So we can use function < string, integer > fun1
- The second time is to convert Integer type to String type
- So we can use function < integer, string > fun2
- String s = fun2.apply(i);
- So we can use function < integer, string > fun2
- We can use the andThen method to combine the two transformations
- String s = fun1.andThen(fun2).apply("123");
- First, call the apply method to convert the string to Integer
- fun2 then calls the apply method to convert the Integer into a string
public class Demo02Function_andThen { /* Define a method An integer of type string Parameters pass two more Function interfaces A generic uses function < string, integer > A generic 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) { //Define 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 + ""; });*/ //Optimizing Lambda change(s, str -> Integer.parseInt(str) + 10, i -> i + ""); } } //Result: 133
3.13 Function interface exercise - user defined function model splicing
- Analysis:
- Intercept the age part of the string to get the string;
Function < string, string > "Zhao Liying, 20" - > "20" - Convert the string of the previous step to a number of type int;
Function<String,Integer> "20"->20 - Add up the int number of the previous step by 100 to get the result int number.
Function<Integer,Integer> 20->120
- Intercept the age part of the string to get the string;
public class Demo03Test { /* Define a method Parameter passes a string containing the name and age Parameters are passed three more Function interfaces for type conversion */ public static int change(String s, Function<String, String> fun1, Function<String, Integer> fun2, Function<Integer, Integer> fun3){ return fun1.andThen(fun2).andThen(fun3).apply(s); } public static void main(String[] args) { //Define a string String str = "Zhao Liying,20"; //Call change method, pass string and 3 Lambda expressions /*int num = change(str, (String s) -> { //Intercept the age part of the number from the string to get the string //"Zhao Liying, 20 "- >" 20“ return s.split(",")[1]; }, (String s) -> { //"20"->20 return Integer.parseInt(s); }, (Integer i) -> { //20->120 return i + 100; });*/ //Simplified Lambda int num = change(str, s -> s.split(",")[1], s -> Integer.parseInt(s), i -> i + 100); System.out.println(num); } } //Result: 120
Published 23 original articles, won praise 5, visited 356