深入理解 lambda表达式 与 函数式编程 函数式接口源码解析(二)
程序员文章站
2022-11-10 14:31:14
一、函数式编程的理解 二、 函数式接口的测试方法 1、Function接口 2、BiFunction接口 3、BinaryOperator接口 4、Predicate接口 5、Supplier接口 三、测试结果 java . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ ......
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.460 info 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.461 info 12080 --- [ main] com.java.design.java8.funcinterface : no active profile set, falling back to default profiles: default 2019-01-31 11:51:58.988 info 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)); } }