Functional interface
- Functional interface
1.1 overview
If there is only one method in an interface, and the default attribute of the method is public abstract method, the interface can be called a functional interface.
1.2 use @ functional interface
Be similar to @Override Turn on code rewrite format strict check /** *Use @ functional interface to check the format of functional interface *A method that requires only one default attribute in the current interface to be public abstract * * @author Anonymous 2020/3/11 9:55 */ @FunctionalInterface public interface FunctionalType { void test(); }
1.3 use the user-defined functional interface as the parameter of the method
package com.qfedu.a_functional; /** * User defined functional interface as parameter of method * * @author Anonymous 2020/3/11 9:55 */ public class Demo1 { public static void main(String[] args) { /* Anonymous inner class is used to complete the use of functional interface, but it is against the purpose of functional interface Low useFunctionalInterface(new FunctionalType() { @Override public void test() { System.out.println("Anonymous objects of anonymous inner classes are directly used as parameters of methods. ""; } }); int(*) (char **, int *) C Function pointer in language In case of C language, the required parameter is method name */ useFunctionalInterface(() -> System.out.println("Functional interface lambda Expression implementation completion method")); } /** * Using a functional interface as a parameter to a method * * @param ft The implementation class object of functional interface, or the nature of direct operation, is directly passed into Lambda expression */ public static void useFunctionalInterface(FunctionalType ft) { ft.test(); } } //Using functional interfaces in code 1. Make the program more purposeful 2. Provide the value of reuse and universality 3. save resources
- The thought of functional programming
2.1 Lambda delay execution
2.1.1 log record
There will be a level limit on whether to save the log //Demonstrate a log log based on different levels //Requirement: //Level = = 1 log log, no other package com.qfedu.b_lambda; enum Level { /** * Enumeration test */ HIGH, MIDDLE, LOWER } /** * Log level record operation * * @author Anonymous 2020/3/11 10:17 */ public class Demo1 { public static void main(String[] args) { /* Here are the questions: "The character superposition process of "+" exception problem XXX "," + "exception time XXX" will generate 5 String These five strings are useful if the Level.HIGH level is used, but they have no effect other than that. MIDDLE,LOWER There is no need for string accumulation, there is a waste of resources. The string accumulation process can only be executed after Level judgment to avoid unnecessary performance waves Fei. Here, you can use the latency of Lambda expression execution to not make words without satisfying the level String accumulation. Functional interface is required here */ log(Level.MIDDLE, "Abnormal position XXX," + "Abnormal problem XXX," + "Abnormal time XXX"); } /** * Judge whether the level needs to record the current log information * * @param level Level, enum type * @param logMsg Log information to be recorded */ public static void log(Level level, String logMsg) { // Determine whether the enumeration type Level.HIGH is met if (Level.HIGH == level) { System.err.println(logMsg); } } }
2.1.2 use functional interface to provide log information function
Here we need a functional interface. The return value type is String Type, others don't matter. package com.qfedu.b_lambda; /** * Provides a functional interface for a method with a return value of type String * * @author Anonymous 2020/3/11 10:52 */ @FunctionalInterface public interface LogMessage { /** * The content of a method in a functional interface. The return value of the method is String * * @return String Type return value */ String returnLogMessage(); } package com.qfedu.b_lambda; /** * Using functional interface to complete Log logging * * @author Anonymous 2020/3/11 10:53 */ public class Demo2 { public static void main(String[] args) { String msg1 = "Abnormal position XXX,"; String msg2 = "Abnormal problem XXX,"; String msg3 = "Abnormal time XXX"; log(Level.LOWER, () -> { System.out.println("Lambda Expression execution!!!"); return msg1 + msg2 + msg3; }); } /** * Determine whether to log according to the log Level * * @param level Level Enumeration type with three data HIGH MIDDLE LOWER * @param lm LogMessage Parameters of functional interface method */ public static void log(Level level, LogMessage lm) { /* It is found that when the Level level is HIGH, execute the corresponding lm.returnLogMessage(); Level Level is not HIGH does not perform the corresponding method. Lambda The problem of execution delay is not that Lambda executes slowly, but that there is an extra judgment before execution The corresponding code can only be executed after judgment. Not executing the code string will not result in the waste of resources caused by splicing, thus improving efficiency. */ if (Level.HIGH == level) { // Get the corresponding returnLogMessage() method through the functional interface System.err.println(lm.returnLogMessage()); } } public static void testEnum(int level) { if (Level.HIGH.getStatus() == level) { } } }
2.2 Lambda as method parameter and return value
Parameter demonstration: Runnable Interface package com.qfedu.b_lambda; /** * Runnable Used as a parameter of a method * * @author Anonymous 2020/3/11 11:18 */ public class Demo3 { public static void main(String[] args) { // Anonymous inner class is used to implement the class object corresponding to the current Runnable interface as the Thread constructor parameter // low new Thread(new Runnable() { @Override public void run() { System.out.println("Thread code"); } }).start(); // Lambda expressions directly as parameters of methods Thread thread = new Thread(() -> { System.out.println("Thread execution takes time"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread execution"); } , "thread"); thread.start(); } } Java Comparison interface provided in Comparator<T> //Using some return values as the adjustment of operation in the method public interface Comparator<T> { int compare(T o1, T o2); } package com.qfedu.b_lambda; import java.util.Arrays; import java.util.Comparator; /** * Lambda Represents a functional interface that uses the return value as the data needed for other operations * * @author Anonymous 2020/3/11 11:25 */ public class Demo4 { public static void main(String[] args) { /* String sort is a dictionary order by default */ String[] arr = {"eeeeeeee", "2a","dddd", "1bb", "ccccccc", "3fffff"}; Arrays.sort(arr); System.out.println(Arrays.toString(arr)); System.out.println("-----------------------------------------"); // Using a functional interface to complete the method, using the return value of the method as the current sort method to run // Required parameter to compare rule constraints Arrays.sort(arr, stringComparator()); System.out.println(Arrays.toString(arr)); System.out.println("-----------------------------------------"); Arrays.sort(arr, (a, b) -> a.length() - b.length()); Arrays.sort(arr, Comparator.comparingInt(String::length)); /* Comparator.comparingInt(String::length) Comparator:Interface comparingInt:Compare and judge according to the type of Int String:Indicates that the type of comparison is String, and what type to use for comparison length:Which way to compare by String type */ System.out.println(Arrays.toString(arr)); } /** * Sorted by string length, the return value type is a comparator < string > interface * Here we need to complete the compare method in the Comparator interface * * @return The Comparator interface of the method body has been completed, and the data type is String */ public static Comparator<String> stringComparator() { /* public interface Comparator<T> { int compare(T o1, T o2); } */ return (a, b) -> b.length() - a.length(); } }
- Common functional interfaces provided in Java
3.1 overview of common functional interfaces of JDK
java.util.function package name. Many functional interfaces are provided Standardized some operations, improved the development efficiency, more focused on the purpose!!! Supplier < T > producer, return a specified type of data Consumer < T > consumer, consuming a specified type of data Predict < T > judge and adjust, filter and use Function < T, R > type conversion, convert to corresponding type R according to the type t you specify
3.2 Supplier producer, return a specified data type
java.util.function.Supplier<T> //There is and only one way T get(); //No parameter required, return the specified T type data //Don't eat anything. All you squeeze is output... package com.qfedu.c_supplier; import com.qfedu.b_lambda.Level; import java.util.function.Supplier; /** * Supplier Functional interface demonstration * * @author Anonymous 2020/3/11 14:44 */ public class Demo1 { public static void main(String[] args) { String msg1 = "Abnormal position XXX,"; String msg2 = "Abnormal problem XXX,"; String msg3 = "Abnormal time XXX"; /* What we need here is a functional interface, directly passing in a lambda expression */ log(Level.HIGH, () -> { System.out.println("Lambda Expression execution!!!"); return msg1 + msg2 + msg3; }); /* Lambda Expression optimization */ log(Level.HIGH, () -> msg1 + msg2 + msg3); } /** * Determine whether to log according to the log Level * * @param level Level Enumeration type with three data HIGH MIDDLE LOWER * @param supplier Supplier Function interface, using T get() to complete the data operation */ public static void log(Level level, Supplier<String> supplier) { /* Supplier The function interface uses the get method to provide the corresponding operation to return the specified String type data */ if (Level.HIGH == level) { // Get the corresponding returnLogMessage() method through the functional interface System.err.println(supplier.get()); } } }
Find the subscript position of the maximum value in the array
package com.qfedu.c_supplier; import java.util.function.Supplier; /** * Using the get method of the functional interface Supplier to find the maximum subscript position in the array * * @author Anonymous 2020/3/11 14:54 */ public class Demo2 { public static void main(String[] args) { int[] array = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10}; /* getMax The parameter required by the method is a Supplier functional interface, which can be completed by using Lambda expression */ int max = getMax(() -> { int index = 0; for (int i = 1; i < array.length; i++) { if (array[index] < array[i]) { index = i; } } return index; }); System.out.println(max); } /** * Using function interface to complete a getMax and provide an operation idea * * @param sup Supplier Functional interface * @return Maximum subscript position */ public static int getMax(Supplier<Integer> sup) { return sup.get(); } }
Introduce the use of functional interface to meet more general codes
package com.qfedu.c_supplier; import java.util.function.Supplier; /** * Demonstrate the use of Supplier functional interface, and its ability to expand methods and * Universal satisfaction * * @author Anonymous 2020/3/11 15:06 */ public class Demo3 { public static void main(String[] args) { Integer[] array = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10}; Integer max = getMax(array, () -> { Integer temp = array[0]; for (int i = 1; i < array.length; i++) { if (temp < array[i]) { temp = array[i]; } } return temp; }); System.out.println(max); System.out.println("-------------------------------------------"); Person[] persons = {new Person(1, "Luo Lei", 16), new Person(2, "black person", 66), new Person(3, "Old payment", 36), new Person(4, "fairly tall", 26), new Person(5, "Foul cloud", 96), new Person(6, "Handsome", 106) }; Person max1 = getMax(persons, () -> { Person p = persons[0]; for (int i = 1; i < persons.length; i++) { if (p.getAge() < persons[i].getAge()) { p = persons[i]; } } return p; }); System.out.println(max1); } /** * Find the largest data in any type of array * * @param arr Array of any type, while constraining the usage rules of current generics * @param sup Supplier Function interface, to use get method to return specified T type data * @param <T> generic paradigm * @return Data consistent with array type */ public static <T> T getMax(T[] arr, Supplier<T> sup) { return sup.get(); } }
3.3 Consumer, processing data
Consumer<T> //The method of operation is void accept(T t); //Receive the corresponding data according to the data type specified by the interface, process and consume it, and there is no external return //As for the process of processing, display, processing, calculation... package com.qfedu.d_consumer; import java.util.function.Consumer; /** * Using Consumer to process data * * @author Anonymous 2020/3/11 15:24 */ public class Demo1 { public static void main(String[] args) { // The method requires a String type parameter and uses the Consumer interface to process data // Because the Consumer interface is a functional interface, you can use Lambda expressions testConsumer("Kung Pao Chicken,Braised Beef Brisket with Tomato,Beef in Brown Sauce,Braised chicken and rice", (str) -> { String[] split = str.split(","); for (String s : split) { System.out.println(s); } }); } /** * Give the current method a String type, and complete the corresponding through the accept method in the Consumer functional interface * string manipulation * * @param str String Type string * @param consumer Consumer Functional interface for data processing */ public static void testConsumer(String str, Consumer<String> consumer) { consumer.accept(str); } }
andThen
package com.qfedu.d_consumer; import java.util.function.Consumer; /** * Consumer Interface andThen use * Two Consumer interfaces are required, and the two Consumer interfaces are combined for data consumption * * andThen(Consumer<T> con) * Invocation format * con1.andThen(con2).accept(T t); * Equivalent to the following operation * con1.accept(t); * con2.accept(t); * * @author Anonymous 2020/3/11 15:57 */ public class Demo2 { public static void main(String[] args) { /* This method requires two Consumer functional interfaces, where two Lambda expression operations can be used */ testAndThen("Zhengzhou refueling!!!Go China!!!", (str) -> System.out.println(str) , (str) -> System.err.println(str) ); } /** * Two Consumer methods are used to process str data. The first is to process the data with con1 and then with con2 * * @param str String type data to be processed * @param con1 Consumer<String> Handle String type functional interface * @param con2 Consumer<String> Handle String type functional interface */ public static void testAndThen(String str, Consumer<String> con1, Consumer<String> con2) { /* con1.accept(str); con2.accept(str); Allow Combo con1.andThen(con2).andThen(con1).andThen(con2).andThen(con1).andThen(con2).accept(str); */ con1.andThen(con2).accept(str); } }
3.4 predict to judge whether the data is suitable, and return true/false
Predicate<T>Generally used for adjusting judgment and filtering data //Methods specified in functional interfaces boolean test(T t); //Handle T type data, return boolean true / false package com.qfedu.e_predicate; import java.util.function.Predicate; /** * Demonstrate basic use of predicate < T > * boolean test(T t) * * @author Anonymous 2020/3/11 16:11 */ public class Demo1 { public static void main(String[] args) { // Predict functional interface, using Lambda expression as parameter of method boolean b = testPredicate("Zhengzhou Origo!!!China orligan!!!", (str) -> { return str.contains("Come on"); }); System.out.println("ret : " + b); System.out.println("---------------------------"); /* Optimize Lambda expressions, Because it's a parameter, parentheses can be omitted For one line of code, braces can be omitted return It can also be omitted */ testPredicate("Zhengzhou Origo!!!China orligan!!!", str -> str.contains("Come on")); } /** * Use the predict function interface to use the boolean test(T t) to judge the current data, * Return boolean type data * * @param str String type string to judge data * @param pre Handle using the predict functional interface * @return Judge whether the interface meets the requirements, return true if it meets the requirements, return false if it does not meet the requirements */ public static boolean testPredicate(String str, Predicate<String> pre) { return pre.test(str); } }
And and
package com.qfedu.e_predicate; import java.util.function.Predicate; /** * Predicate and Use * default Modification method add (predicate < T > pre) * and It's in logical operators&& * If the same truth is true, there is a false [i.e.] false * Two predictes need to be judged * * For example: * pre1.test(str) && pre2.test(srt); * ==> pre1.and(pre2).test(str); * * @author Anonymous 2020/3/11 16:19 */ public class Demo2 { public static void main(String[] args) { /* Here, we need to use the predict interface, which uses Lambda */ boolean ret = testAnd("Get back to work now, don't do anything!!!", str -> str.length() > 5, str -> str.startsWith("Hurry up")); System.out.println(ret); } /** * Combinatorial judgement * * @param str String to judge * @param pre1 Judgment mode 1 * @param pre2 Judgment mode 2 * @return Processing result true, false */ public static boolean testAnd(String str, Predicate<String> pre1, Predicate<String> pre2) { // return pre1.test(str) && pre2.test(str) return pre1.and(pre2).test(str); } }
Or or
package com.qfedu.e_predicate; import java.util.function.Predicate; /** * Predicate or Demonstration * * @author Anonymous 2020/3/11 16:32 */ public class Demo3 { public static void main(String[] args) { boolean ret = testOr("The power of the country is beyond the envy of foreigners~~", str -> str.length() < 10, str -> str.contains("Country")); System.out.println(ret); } /** * or Combinatorial judgement * * @param str String to judge * @param pre1 Judgment mode 1 * @param pre2 Judgment mode 2 * @return Processing result true, false */ public static boolean testOr(String str, Predicate<String> pre1, Predicate<String> pre2) { // return pre1.test(str) || pre2.test(str); return pre1.or(pre2).test(str); } }
negate non
package com.qfedu.e_predicate; import java.util.function.Predicate; /** * Predicate negate()operation * * @author Anonymous 2020/3/11 16:36 */ public class Demo4 { public static void main(String[] args) { boolean ret = testNegate("The epidemic will pass!!!", str -> str.length() < 5); System.out.println(ret); } /** * negate operation * * @param str Character string * @param pre Predicate Functional interface * @return Processing result */ public static boolean testNegate(String str, Predicate<String> pre) { // return !pre.test(str); return pre.negate().test(str); } }
Delete the specified data with Predicate in ArrayList
package com.qfedu.e_predicate; import com.qfedu.c_supplier.Person; import java.util.ArrayList; /** * ArrayList,Using Predicate as a constraint to delete the corresponding data * * @author Anonymous 2020/3/11 16:41 */ public class Demo5 { public static void main(String[] args) { ArrayList<Person> list = new ArrayList<>(); list.add(new Person(1, "Luo Lei", 16)); list.add(new Person(2, "black person", 66)); list.add(new Person(3, "Old payment", 36)); list.add(new Person(4, "fairly tall", 26)); list.add(new Person(5, "Foul cloud", 96)); list.add(new Person(6, "Handsome", 96)); // Directly arrange the Predicate function interface to constrain the corresponding conditions and delete them // Code reading and universality improvement // And reduced code redundancy list.removeIf(person -> person.getAge() > 40 && person.getId() > 3); System.out.println(list); } }
3.5 function < T, R > type conversion
Use R apply(T t) //Convert specified type T to R package com.qfedu.f_function; import com.qfedu.c_supplier.Person; import java.util.function.Function; /** * Function<T, R> Functional interface * R apply(T) * * @author Anonymous 2020/3/11 16:50 */ public class Demo1 { public static void main(String[] args) { // Integer type converted to a String String change = change(10, i -> i + ""); System.out.println(change); // Use function interface to process a String type and convert it to the corresponding Person type Person person1 = change("1,Luo Lei,16", str -> { String[] split = str.split(","); Person person = new Person(); person.setId(Integer.parseInt(split[0])); person.setName(split[1]); person.setAge(Integer.parseInt(split[2])); return person; }); System.out.println(person1); } /** * The method of converting format, which requires data to be converted from Integer type to specified String type * * @param i Integer type to convert * @param fun Function functional interface used for conversion * @return The return value is of String type */ public static String change(Integer i, Function<Integer, String> fun) { return fun.apply(i); } public static Person change(String str, Function<String, Person> fun) { return fun.apply(str); } }
andThen
package com.qfedu.f_function; import java.util.function.Function; /** * Function<T, R> * default Modify the use of the andThen method * * @author Anonymous 2020/3/11 17:01 */ public class Demo2 { public static void main(String[] args) { String s = testAndThen(10, i -> i + "", i -> i + "test"); System.out.println(s); } /** * Two conversion processes * * @param i Types to process * @param fun1 Function Function interface * @param fun2 Function Function interface * @return String type */ public static String testAndThen(int i, Function<Integer, String> fun1, Function<String, String> fun2) { // andThen, finally, apply method parameter type is the conversion parameter type required by fun1 return fun1.andThen(fun2).apply(i); } }