深入理解 lambda表示式 與 函數語言程式設計 函式式介面原始碼解析(二)
package com.java.design.java8; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.function.*; import java.util.stream.Collectors; /** * @author 陳楊 */ @RunWith(SpringRunner.class) @SpringBootTest public class FuncInterface {
一、函數語言程式設計的理解
//函數語言程式設計的理解 // //函式介面式程式設計 是 對 業務應用的進一步抽象 //在類方法定義中 只需實現FunctionalInterface 而不管業務實現的邏輯 //在外部應用 呼叫該業務時 使用Lambda表示式 靈活實現其業務邏輯
二、 函式式介面的測試方法
1、Function介面
//Function Function<Integer, Integer> sum = integer -> integer + 1; Function<Integer, Integer> multiply = integer -> integer * integer; List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0); public int testFunctionCompose(Integer integer) { return sum.compose(multiply).apply(integer); } public int testFunctionAndThen(Integer integer) { return sum.andThen(multiply).apply(integer); }
2、BiFunction介面
//BiFunction BiFunction<Integer, Integer, Integer> subtract = (first, last) -> first - last; public int testBiFunctionAndThen(Integer first, Integer last) { return subtract.andThen(multiply).apply(first, last); }
3、BinaryOperator介面
//BinaryOperator BinaryOperator<Integer> binaryOperator = (first, last) -> first - last; public int testBinaryOperator(Integer first, Integer last) { return binaryOperator.apply(first, last); } public String testMinBy(String first, String last, Comparator<String> comparator) { return BinaryOperator.minBy(comparator).apply(first, last); } public String testMaxBy(String first, String last, Comparator<String> comparator) { return BinaryOperator.maxBy(comparator).apply(first, last); }
//比較器 //比較字串的長度 Comparator<String> length = (first, last) -> first.length() - last.length(); //比較字串首字母ASCII碼大小 Comparator<String> asc = (first, last) -> first.charAt(0) - last.charAt(0);
4、Predicate介面
//Predicate public List<Integer> testPredicate(Predicate<Integer> predicate) { return list.stream().filter(predicate).collect(Collectors.toList()); } public Predicate<String> isEqual(Object object) { return Predicate.isEqual(object); } public Predicate<Integer> notPredicate(Predicate<Integer> predicate) { return Predicate.not(predicate); } public List<Integer> testPredicateNegate(Predicate<Integer> predicate) { return list.stream().filter(predicate.negate()).collect(Collectors.toList()); } public List<Integer> testPredicateAnd(Predicate<Integer> first, Predicate<Integer> last) { return list.stream().filter(first.and(last)).collect(Collectors.toList()); } public List<Integer> testPredicateOr(Predicate<Integer> first, Predicate<Integer> last) { return list.stream().filter(first.or(last)).collect(Collectors.toList()); }
5、Supplier介面
//Supplier @Data @AllArgsConstructor @NoArgsConstructor private class Student { private Integer id; private String name; private String sex; private Integer age; private String addr; private Double salary; }
三、測試結果
._______ _ _ /\\ / ___'_ __ _ _(_)_ ____ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/___)| |_)| | | | | || (_| |) ) ) ) '|____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot ::(v2.1.2.RELEASE) 2019-01-31 11:51:58.460INFO 12080 --- [main] com.java.design.java8.FuncInterface: Starting FuncInterface on DESKTOP-87RMBG4 with PID 12080 (started by 46250 in E:\IdeaProjects\design) 2019-01-31 11:51:58.461INFO 12080 --- [main] com.java.design.java8.FuncInterface: No active profile set, falling back to default profiles: default 2019-01-31 11:51:58.988INFO 12080 --- [main] com.java.design.java8.FuncInterface: Started FuncInterface in 0.729 seconds (JVM running for 1.556) --------------------Function介面的理解--------------------- 65 81 ------------------BiFunction介面的理解--------------------- 64 -------------------Predicate介面的理解--------------------- 獲取滿足條件的集合:大於4 [5, 6, 7, 8, 9] ------------------------------ 獲取滿足條件的集合:大於4且是偶數 [6, 8] ------------------------------ 獲取滿足條件的集合:大於4取反 [1, 2, 3, 4, 0] ------------------------------ 獲取滿足條件的集合:大於4或是偶數 [2, 4, 5, 6, 7, 8, 9, 0] ------------------------------ 使用Objects的Equals方法判斷物件是否相同 true ------------------------------ Predicate.not()返回(Predicate<T>)target.negate(); [1, 2, 3, 4, 0] ------------------------------ 雙重否定表肯定 [5, 6, 7, 8, 9] ------------------------------ -------------------Supplier介面的理解--------------------- FuncInterface.Student(id=1, name=Kirito, sex=Male, age=18, addr=ShenZhen, salary=9.99999999E8) ------------------------------ ---------------BinaryOperator介面的理解------------------- 整合BiFunction的Apply方法 實現減法 10 - 2 = 8 ------------------------------ 字串較短的是:Asuna 字串較長的是:Kirito ------------------------------ 字串首字母ASCII碼較小的是:Asuna 字串首字母ASCII碼較大的是:Kirito Process finished with exit code 0
四、透過現象看本質 函式式介面的原始碼實現
1、Function介面
@Test public void testFuncInterface() { System.out.println("--------------------Function介面的理解---------------------\n"); //Function介面的理解 //public interface Function<T, R> //R apply(T t); //Represents a function that accepts one argument and produces a result. //一個函式:接收一個引數 返回一個結果 //T 輸入型別 R 輸出型別 /*default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } * Returns a composed function that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. */ //輸入-->beforeFunction()處理-->得到結果作為下一個函式apply()的輸入引數形成函式式介面的串聯呼叫 //beforeFunction 在當前函式apply前 進行呼叫 /*default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. */ //輸入-->apply()處理-->得到結果作為下一個函式after.apply()的輸入引數形成函式式介面的串聯呼叫 //afterFunction 在當前函式apply後 進行呼叫 /*static <T> Function<T, T> identity() { return t -> t; * Returns a function that always returns its input argument. }*/ //總是返回輸入引數 //總結: //function1.compose(function2)執行順序 -->BeforeFunction()-->thisFunction()-->function2 --> function1 //function1.andThen(function2)執行順序 -->thisFunction()-->AfterFunction()-->function1 --> function2 //前一個函式的運算結果 作為下一個函式的輸入引數 //理解執行時機 可以類比 Junit中 @Before 與 @After System.out.println(this.testFunctionCompose(8)); System.out.println(this.testFunctionAndThen(8));
2、BiFunction介面
System.out.println("------------------BiFunction介面的理解---------------------\n"); //BiFunction 介面 的 理解 //@FunctionalInterface //public interface BiFunction<T, U, R> { //R apply(T t, U u); //一個函式:接收二個引數 返回一個結果 /* default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t, U u) -> after.apply(apply(t, u)); } } */ //利用反證法 可以證明BiFunction 沒有 compose方法(提示: 引數 與 返回值) //將2個引數應用於BiFunction 只會得到一個返回值 這個返回值會作為Function傳入的引數 //biFunction.andthen(function) System.out.println(this.testBiFunctionAndThen(10, 2));
3、Predicate介面
System.out.println("-------------------Predicate介面的理解---------------------\n"); //public interface Predicate<T> { //Represents a predicate (boolean-valued function) of one argument. /* *Evaluates this predicate on the given argument. * *接收一個判斷 判斷是否滿足預期條件 返回true false *boolean test(T t); */ System.out.println("獲取滿足條件的集合:大於4"); System.out.println(this.testPredicate(in -> in > 4)); System.out.println("------------------------------\n"); /* *Returns a composed predicate that represents a short-circuiting logical *AND of this predicate and another.When evaluating the composed *predicate, if this predicate is {@code false}, then the {@code other} *predicate is not evaluated. * *短路邏輯與計算 *default Predicate<T> and(Predicate<? super T> other) { *Objects.requireNonNull(other); *return (t) -> test(t) && other.test(t); }*/ System.out.println("獲取滿足條件的集合:大於4且是偶數"); System.out.println(this.testPredicateAnd(in -> in > 4, in -> in % 2 == 0)); System.out.println("------------------------------\n"); /* *Returns a predicate that represents the logical negation of this *predicate. * *取反 *default Predicate<T> negate() { *return (t) -> !test(t); *} */ System.out.println("獲取滿足條件的集合:大於4取反"); System.out.println(this.testPredicateNegate(in -> in > 4)); System.out.println("------------------------------\n"); /* *Returns a composed predicate that represents a short-circuiting logical *OR of this predicate and another.When evaluating the composed *predicate, if this predicate is {@code true}, then the {@code other} *predicate is not evaluated. * *短路邏輯或計算 *default Predicate<T> or(Predicate<? super T> other) { *Objects.requireNonNull(other); *return (t) -> test(t) || other.test(t); *} */ System.out.println("獲取滿足條件的集合:大於4或是偶數"); System.out.println(this.testPredicateOr(in -> in > 4, in -> in % 2 == 0)); System.out.println("------------------------------\n"); /* *Returns a predicate that tests if two arguments are equal according *to {@link Objects#equals(Object, Object)}. * *根據Objects的equals方法 來判斷兩個物件 是否相同 *static <T> Predicate<T> isEqual(Object targetRef) { *return (null == targetRef) *? Objects::isNull *: object -> targetRef.equals(object); *} */ System.out.println("使用Objects的Equals方法判斷物件是否相同"); System.out.println(this.isEqual("Kirito").test("Kirito")); System.out.println("------------------------------\n"); /* *Returns a predicate that is the negation of the supplied predicate. *This is accomplished by returning result of the calling *{@code target.negate()}. * *返回提供的predicate的否定 *@SuppressWarnings("unchecked") *static <T> Predicate<T> not(Predicate<? super T> target) { *Objects.requireNonNull(target); *return (Predicate<T>)target.negate(); *} *} */ System.out.println("Predicate.not()返回(Predicate<T>)target.negate(); "); System.out.println(testPredicate(this.notPredicate(integer -> integer > 4))); System.out.println("------------------------------\n"); System.out.println("雙重否定表肯定"); System.out.println(testPredicateNegate(this.notPredicate(integer -> integer > 4))); System.out.println("------------------------------\n");
4、Supplier介面
System.out.println("-------------------Supplier介面的理解---------------------\n"); /* *Represents a supplier of results. * *public interface Supplier<T> { *T get(); *} */ //構造方法引用建構函式介面例項 //利用Supplier介面Student類必須要有無參的構造方法 //Supplier<Student> studentSupplier = () -> new Student(); Supplier<Student> studentSupplier = Student::new; Student student = studentSupplier.get(); student.setId(1); student.setName("Kirito"); student.setSex("Male"); student.setAge(18); student.setSalary(999999999.0); student.setAddr("ShenZhen"); System.out.println(student); System.out.println("------------------------------\n");
5、BinaryOperator介面
System.out.println("---------------BinaryOperator介面的理解-------------------\n"); /* * *public interface BinaryOperator<T> extends BiFunction<T,T,T> { * *返回2個比較引數之間的較小值 *public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) { *Objects.requireNonNull(comparator); *return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; *} * *返回2個比較引數之間的較大值 *public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) { *Objects.requireNonNull(comparator); *return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; *} *} */ System.out.println("整合BiFunction的Apply方法 實現減法"); System.out.println("10 - 2 = "+this.testBinaryOperator(10, 2)); System.out.println("------------------------------\n"); System.out.println("字串較短的是:"+this.testMinBy("Kirito","Asuna",length)); System.out.println("字串較長的是:"+this.testMaxBy("Kirito","Asuna",length)); System.out.println("------------------------------\n"); System.out.println("字串首字母ASCII碼較小的是:"+this.testMinBy("Kirito","Asuna",asc)); System.out.println("字串首字母ASCII碼較大的是:"+this.testMaxBy("Kirito","Asuna",asc)); } }