网站建设申报方案,金融平台网站开发,昆明市网站制作公司,水土保持与生态建设网站函数式编程是一种编程规范或一种编程思想#xff0c;简单可以理解问将运算或实现过程看做是函数的计算。 Java8为了实现函数式编程#xff0c;提出了3个重要的概念#xff1a;Lambda表达式、方法引用、函数式接口。现在很多公司都在使用lambda表达式进行代码编写#xff0c…函数式编程是一种编程规范或一种编程思想简单可以理解问将运算或实现过程看做是函数的计算。 Java8为了实现函数式编程提出了3个重要的概念Lambda表达式、方法引用、函数式接口。现在很多公司都在使用lambda表达式进行代码编写甚至知名的Java的插件也都在Lambda比如数据库插件MybatisPlus。Lambda表达式的使用是需要函数式接口的支持即lambda表达式的核心就是使用大量的函数式接口。本文带领大家全面了解函数式接口的定义和使用。 一、文章导读 函数式接口概述 自定义函数式接口 常用函数式接口 函数式接口的练习 二、函数式接口概述 1.函数式接口定义 如果接口里只有一个抽象方法那么就是函数式接口可以使用注解(FunctionalInterface)检测该接口是否是函数式接口即只能有一个抽象方法。 注意事项 函数式接口里可以定义默认方法默认方法有方法体,不是抽象方法,符合函数式接口的定义要求。 函数式接口里可以定义静态方法静态方法也不是抽象方法,是一个有具体方法实现的方法,同样也符合函数式接口的定义的。 函数式接口里可以定义Object里的public方法(改成抽象方法)虽然它们是抽象方法,却不需要覆盖重写,因为所有接口的实现类都是Object类的子类,而在Object类中有这些方法的具体的实现。 2.函数式接口格式java
修饰符 interface 接口名称 {//抽象方法publicabstract 返回值类型 方法名称(可选参数信息);//默认方法publicdefault 返回值类型 方法名称(可选参数信息){//代码... }//静态方法publicstatic 返回值类型 方法名称(可选参数信息){//代码... }//Object类的public方法变成抽象方法publicabstractbooleanequals(Object obj);publicabstractStringtoString();}三、自定义函数式接口自定义函数式接口举例 由于接口当中抽象方法的public abstract是可以省略的所以定义一个函数式接口很简单java
FunctionalInterfacepublicinterfaceMyFunctionalInterface{//抽象方法publicabstractvoidmethod();//Object类的public方法变成抽象方法publicabstractbooleanequals(Object obj);publicabstractStringtoString();//默认方法publicdefaultvoidshow(String s){//打印小写System.out.println(s.toLowerCase());}//静态方法publicstaticvoidprint(String s){//打印大写System.out.println(s.toUpperCase());}}2.自定义函数式接口的应用 对于刚刚定义好的MyFunctionalInterface函数式接口典型使用场景就是作为方法的参数java
publicclassDemo01FunctionalInterface{publicstaticvoidmain(String[] args){// 调用使用函数式接口的方法show(()-{System.out.println(Lambda执行了);});}//定义方法使用函数式接口作为参数publicstaticvoidshow(MyFunctionalInterface mfi){//调用自己定义的函数式接口mfi.method();String s mfi.toString();System.out.println(s);boolean result mfi.equals(mfi);System.out.println(result);mfi.show(world);MyFunctionalInterface.print(function);}}3.运行结果:
Lambda执行了
Demo01FunctionalInterface$$Lambda$1/10786947893d075dc0true
world
FUNCTION四、常用函数式接口 前面我们自己定义了一个函数式接口,对于一些常用的函数式接口,每次自己定义非常麻烦。JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景它们主要在java.util.function包中被提供。这样的接口有很多下面是最简单的几个接口及使用示例。Supplier接口 java.util.function.Supplier接口它意味着供给 , 对应的Lambda表达式需要“**对外提供**”一个符合泛型类型的对象数据。 1.1.抽象方法 : get Supplier接口中包含一个抽象方法 T get(): 用来获取一个泛型参数指定类型的对象数据。javapublicclassDemo02Supplier{publicstaticvoidmain(String[] args){int num getNum(()-{returnnewRandom().nextInt();});System.out.println(num);}publicstaticintgetNum(SupplierInteger supplier){int num supplier.get();return num;}}1.2.求集合元素最大值 使用Supplier接口作为方法参数类型通过Lambda表达式求出List集合(存储int数据)中的最大值。提示接口的泛型请使用java.lang.Integer类。 代码示例:java
publicclassDemo03Supplier{publicstaticvoidmain(String[] args){ListInteger list newArrayList();Collections.addAll(list,10,8,20,3,5);printMax(()-{returnCollections.max(list);});}privatestaticvoidprintMax(SupplierInteger supplier){int max supplier.get();System.out.println(max);}}2. Consumer接口 java.util.function.Consumer接口则正好相反它不是生产一个数据而是**消费**一个数据其数据类型由泛型参数决定。 2.1.抽象方法accept Consumer接口中包含抽象方法void accept(T t): 消费一个指定泛型的数据。 代码示例:java
importjava.util.function.Consumer;//接收一个输入参数x,把x的值扩大2倍后,再3做输出//类似于数学中的函数: f(x) 2*x 3publicclassDemo04Consumer{publicstaticvoidmain(String[] args){int x 3;consumeIntNum(x,(Integer num)-{System.out.println(2*num3);});}/*定义方法,使用函数式接口Consumer作为方法参数*/privatestaticvoidconsumeIntNum(int num,ConsumerInteger function ){function.accept(num);}}
#### 2.2.默认方法andThen如果一个方法的参数和返回值全都是Consumer类型那么就可以实现效果消费一个数据的时候首先做一个操作然后再做一个操作实现组合。而这个方法就是Consumer接口中的default方法andThen。下面是JDK的源代码java
defaultConsumerTandThen(Consumer?superT after){Objects.requireNonNull(after);return(T t)-{accept(t); after.accept(t);};}2.2.默认方法andThen 如果一个方法的参数和返回值全都是Consumer类型那么就可以实现效果消费一个数据的时候首先做一个操作然后再做一个操作实现组合。而这个方法就是Consumer接口中的default方法andThen。下面是JDK的源代码java
defaultConsumerTandThen(Consumer?superT after){Objects.requireNonNull(after);return(T t)-{accept(t); after.accept(t);};}备注java.util.Objects的requireNonNull静态方法将会在参数为null时主动抛出NullPointerException异常。这省去了重复编写if语句和抛出空指针异常的麻烦。 andThen是默认方法,由Consumer的对象调用,而且参数和返回值都是Consumer对象 要想实现组合需要两个或多个Lambda表达式即可而andThen的语义正是“一步接一步”操作。例如两个步骤组合的情况 代码示例:java
//接收一个字符串,先按照大写打印,再按照小写打印/*toUpperCase(): 把字符串变成大写toLowerCase(): 把字符串变成小写*/publicclassDemo05Consumer{publicstaticvoidmain(String[] args){String s Hello;//lambda标准格式fun(s,(String str)-{System.out.println(s.toUpperCase());},(String str)-{System.out.println(s.toLowerCase());});}/*定义方法,参数是Consumer接口因为要消费两次,所以需要两个Consumer接口作为参数*/publicstaticvoidfun(String s,ConsumerString con1,ConsumerString con2){//先消费一次con1.accept(s);//再消费一次con2.accept(s);}}运行结果将会首先打印完全大写的HELLO然后打印完全小写的hello。但是我们却没有使用andThen方法,其实我上面的写法,就是andThen底层的代码实现。 为了方便大家理解,下面我们使用andThen方法进行演示。java
publicclassDemo06Consumer{publicstaticvoidmain(String[] args){String s HelloWorld;//2.lambda标准格式fun(s,(String str)-{System.out.println(s.toUpperCase());},(String str)-{System.out.println(s.toLowerCase());});}/*定义方法,参数是Consumer接口因为要消费两次,所以需要两个Consumer接口作为参数*/publicstaticvoidfun(String s,ConsumerString con1,ConsumerString con2){con1.andThen(con2).accept(s);}}运行结果将会首先打印完全大写的HELLO然后打印完全小写的hello。 andThen原理分析图解 txt 注意: 1.con1调用andThen方法,传递参数con2,所以anThen方法内部的this就是con1,after就是con2 2.andThen方法内部调用accept方法,前面隐藏了一个this,this代表调用andThen方法的对象,就是con1 3.andThen方法内部的t是谁?就是最后调用方法accept传递的s this.accept(t) con1.accept(s) ① 4.con1调用andThen方法时传递的参数是con2,所以andThen方法内部的after就是con2 after.accept(t) con2.accept(s) ② 5.通过分析,我们发现①和②中的内容,就是之前不用andThen方法,自己进行调用的过程 6.以上分析,仍然是按照面向对象中方法调用的思路展开的,但实质上,我们要注意,Consumer接口中的andThen方法,返回的是一个Consumer,里面采用的是lambda表达式,其实是在做函数模型的拼接,把两个函数模型con1和con2拼接出一个新的模型,返回新的模型。所以con1.andThen(con2)是把con1和con2拼接成一个新的Consumer,返回的是lambda表达式的形式 最后调用accept(s)方法时,其实执行的是lambda表达式{}中的代码、、、 3. Function接口 java.util.function.Function接口用来根据一个类型的数据得到另一个类型的数据前者称为前置条件后者称为后置条件。有进有出所以称为“函数Function”。 3.1.抽象方法apply Function接口中最主要的抽象方法为R apply(T t)根据类型T的参数获取类型R的结果。 代码示例: 将String类型转换为Integer类型。java
/*java.util.function.FunctionT,R: 转换型接口泛型T: 转换前的类型泛型R: 转换后的类型抽象方法:R apply(T t): 根据类型T的参数获取类型R的结果 把参数t转换成R类型的结果123 -- 123需求:给你一个String类型的数字,给我转换成int数字分析:用Function接口T: 转换前的类型, StringR: 转换后的类型, Integer*/publicclassDemo07Function{publicstaticvoidmain(String[] args){String s 123;//lambda标准格式fun(s,(String str)-{returnInteger.parseInt(str);});}/*定义方法,使用Function接口作为参数*/publicstaticvoidfun(String s,FunctionString,Integer function){Integer num function.apply(s);System.out.println(num);}}3.2.默认方法andThen Function接口中有一个默认的andThen方法用来进行组合操作。JDK源代码如java
defaultVFunctionT,VandThen(Function?superR,?extendsV after){Objects.requireNonNull(after);return(T t)- after.apply(apply(t));}该方法同样用于“先做什么再做什么”的场景和Consumer中的andThen差不多 代码示例: 将String的数字,转成int数字,再把int数字扩大10倍java
/*java.util.function.FunctionT,R: 转换型接口泛型T: 转换前的类型泛型R: 转换后的类型默认方法:default V FunctionT, V andThen(FunctionR, V after):先转换一次,再转换一次,一个挨着一个123 -- 123 -- 1230 (扩大了10倍)需求:给你一个String类型的数字,给我转先换成int数字再给我把int数字扩大10倍分析:用2个Function接口第一个Function接口T: 转换前的类型, StringR: 转换后的类型, Integer第二个Function接口:T: 转换前的类型, IntegerR: 转换后的类型, Integer*/publicclassDemo08Function{publicstaticvoidmain(String[] args){String s 123;//lambda标准格式fun(s,(String str)-{returnInteger.parseInt(str);},(Integer num)-{return num*10;});}/*定义一个方法,有两个Function接口作为参数*/publicstaticvoidfun(String s,FunctionString,Integer fun1,FunctionInteger,Integer fun2){//1.先转换一次Integer num1 fun1.apply(s);//2.再转换一次Integer num2 fun2.apply(num1);System.out.println(num2);}}第一个操作是将字符串解析成为int数字第二个操作是乘以10。两个操作通过andThen按照前后顺序组合到了一起。运行结果将会打印1230。但是我们却没有使用andThen方法,其实我上面的写法,就是andThen底层的代码实现。 请注意Function的前置条件泛型和后置条件泛型可以相同。 为了方便大家理解,下面我们使用andThen方法进行演示 publicclassDemo09Function{publicstaticvoidmain(String[] args){String s 123;//lambda标准格式fun(s,(String str)-{returnInteger.parseInt(str);},(Integer num)-{return num*10;});}/*定义一个方法,有两个Function接口作为参数*/publicstaticvoidfun(String s,FunctionString,Integer fun1,FunctionInteger,Integer fun2){Integer num3 fun1.andThen(fun2).apply(s);System.out.println(num3);}}运行结果仍然是1230。 andThen原理分析图解 txt 注意: 1.fun1调用andThen方法传递参数fun2,所以andThen方法内部的this就是fun1,after就是fun2 2.andThen方法内部直接调用apply方法,前面隐藏了一个this,this代表调用andThen方法的对象,就是fun1 3.andThen方法内部的t是谁?就是最后调用方法apply传递的s this.apply(t) Integer num1 fun1.apply(s) ① 4.fun1调用andThen方法时传递的参数是fun2,所以andThen方法内部的after就是fun2 after.apply(this.apply(t)) Integer num2 fun2.apply(num1) ② 5.通过分析,我们发现①和②中的内容,就是之前不用andThen方法,我们自己进行调用的过程 6.以上分析,仍然是按照面向对象中方法调用的思路展开的,但实质上,我们要注意,Function接口中的andThen方法,返回的是一个Function,里面采用的是lambda表达式,其实是在做函数模型的拼接,把两个函数模型fun1和fun2拼接出一个新的模型,返回新的模型。所以fun1.andThen(fun2)是把fun1和fun2拼接成一个新的Function,返回的是lambda表达式的形式 最后调用accept(s)方法时,其实执行的是lambda表达式{}中的代码 4. Predicate接口 有时候我们需要对某种类型的数据进行判断从而得到一个boolean值结果。这时可以使用java.util.function.Predicate接口。 4.1.抽象方法test Predicate接口中包含一个抽象方法boolean test(T t)。用于条件判断的场景java
//1.练习:判断字符串长度是否大于5//2.练习:判断字符串是否包含HpublicclassDemo10Predicate{publicstaticvoidmain(String[] args){String str helloWorld;//1.练习:判断字符串长度是否大于5//lambda标准格式fun(str,(String s)-{return s.length()5;});System.out.println(-----------------);//2.练习:判断字符串是否包含H//lambda标准格式fun(str,(String s)-{return s.contains(H);});}/*定义一个方法,参数是Predicate接口*/publicstaticvoidfun(String s,PredicateStringpredicate){boolean result predicate.test(s);System.out.println(result);}}条件判断的标准是传入的Lambda表达式逻辑只要字符串长度大于5则认为很长。 4.2.默认方法and 既然是条件判断就会存在与、或、非三种常见的逻辑关系。其中将两个Predicate条件使用“与”逻辑连接起来实现“**并且**”的效果时可以使用default方法and。其JDK源码为java
defaultPredicateTand(Predicate?superT other){Objects.requireNonNull(other);return(t)-test(t) other.test(t);}代码示例: 判断一个字符串既要包含大写“H”又要包含大写“W”java
publicclassDemo11Predicate{publicstaticvoidmain(String[] args){String str HelloWorld;//1.练习:判断一个字符串既要包含大写“H”又要包含大写“W”//lambda标准格式fun1(str,(String s)-{return s.contains(H);},(String s)-{return s.contains(W);});System.out.println(------------);fun2(str,(String s)-{return s.contains(H);},(String s)-{return s.contains(W);});}/*演示and方法需要两个Predicate作为参数fun1方法没有使用and方法,就是p1和p2分别调用test方法,然后把结果进行运算--其实这是and方法的底层实现*/publicstaticvoidfun(String s,PredicateString p1,PredicateString p2){//先判断一次boolean result1 p1.test(s);//再判断一次boolean result2 p2.test(s);//进行运算boolean result result1result2;System.out.println(result);}/*演示and方法需要两个Predicate作为参数*/publicstaticvoidfun2(String s,PredicateString p1,PredicateString p2){boolean result p1.and(p2).test(s);System.out.println(result);}} 4.3.默认方法or 与and的“与”类似默认方法or实现逻辑关系中的“**或**”。JDK源码为java
defaultPredicateTor(Predicate?superT other){Objects.requireNonNull(other);return(t)-test(t)|| other.test(t);}代码示例: 字符串包含大写H或者包含大写W”java
publicclassDemo12Predicate{publicstaticvoidmain(String[] args){String str Helloworld;//1.练习:判断一个字符串包含大写“H”或者包含大写“W”//lambda标准格式fun1(str,(String s)-{return s.contains(H);},(String s)-{return s.contains(W);});System.out.println(------------);fun2(str,(String s)-{return s.contains(H);},(String s)-{return s.contains(W);});}/*演示or方法需要两个Predicate作为参数fun1方法没有使用or方法,就是p1和p2分别调用test方法,然后把结果进行||运算--其实这是or方法的底层实现*/publicstaticvoidfun(String s,PredicateString p1,PredicateString p2){//先判断一次boolean result1 p1.test(s);//再判断一次boolean result2 p2.test(s);//进行||运算boolean result result1||result2;System.out.println(result);}/*演示or方法需要两个Predicate作为参数*/publicstaticvoidfun2(String s,PredicateString p1,PredicateString p2){boolean result p1.or(p2).test(s);System.out.println(result);}} 关于and和or方法的原理,可以参考andThen方法原理 4.4.默认方法negate “与”、“或”已经了解了剩下的“非”(取反)也会简单。默认方法negate的JDK源代码为java
defaultPredicateTnegate(){return(t)-!test(t);}从实现中很容易看出它是执行了test方法之后对结果boolean值进行“!”取反而已。一定要在test方法调用之前调用negate方法正如and和or方法一样java
importjava.util.function.Predicate;publicclassDemo13Predicate{privatestaticvoidmethod(PredicateString predicate,String str){boolean veryLong predicate.negate().test(str);System.out.println(字符串很长吗 veryLong);}publicstaticvoidmain(String[] args){method(s - s.length()5,Helloworld);}}五、总结 本文通过具体的例子演示了函数式接口的定义和使用。以及常用的函数式接口。并给出了相关的练习题目。对于部分函数式接口中的默认方法进行了图解分析让你更加深刻的理解函数式接口的思想和目的。在以后实际的编程过程中对于集合的操作,可以通过Stream流完成,而Stream流中的很多方法的参数都是函数式接口,通过本文的学习,你已经掌握了函数式接口的使用,相信后面学习Stream流是非常容易的。
文章转载自: http://www.morning.yixingshengya.com.gov.cn.yixingshengya.com http://www.morning.pznhn.cn.gov.cn.pznhn.cn http://www.morning.fnczn.cn.gov.cn.fnczn.cn http://www.morning.pswzc.cn.gov.cn.pswzc.cn http://www.morning.mzqhb.cn.gov.cn.mzqhb.cn http://www.morning.jxpwr.cn.gov.cn.jxpwr.cn http://www.morning.ysfj.cn.gov.cn.ysfj.cn http://www.morning.slqgl.cn.gov.cn.slqgl.cn http://www.morning.bktly.cn.gov.cn.bktly.cn http://www.morning.hxfrd.cn.gov.cn.hxfrd.cn http://www.morning.xrrjb.cn.gov.cn.xrrjb.cn http://www.morning.rrdch.cn.gov.cn.rrdch.cn http://www.morning.mfnjk.cn.gov.cn.mfnjk.cn http://www.morning.dnqliv.cn.gov.cn.dnqliv.cn http://www.morning.kjkml.cn.gov.cn.kjkml.cn http://www.morning.mcpby.cn.gov.cn.mcpby.cn http://www.morning.qtyfb.cn.gov.cn.qtyfb.cn http://www.morning.ryqsq.cn.gov.cn.ryqsq.cn http://www.morning.kzrg.cn.gov.cn.kzrg.cn http://www.morning.pjjkz.cn.gov.cn.pjjkz.cn http://www.morning.qmmfr.cn.gov.cn.qmmfr.cn http://www.morning.hsgxj.cn.gov.cn.hsgxj.cn http://www.morning.fylsz.cn.gov.cn.fylsz.cn http://www.morning.kwnbd.cn.gov.cn.kwnbd.cn http://www.morning.wptrm.cn.gov.cn.wptrm.cn http://www.morning.nzfqw.cn.gov.cn.nzfqw.cn http://www.morning.dansj.com.gov.cn.dansj.com http://www.morning.dfmjm.cn.gov.cn.dfmjm.cn http://www.morning.lqchz.cn.gov.cn.lqchz.cn http://www.morning.fbdtd.cn.gov.cn.fbdtd.cn http://www.morning.wnxqf.cn.gov.cn.wnxqf.cn http://www.morning.skql.cn.gov.cn.skql.cn http://www.morning.brps.cn.gov.cn.brps.cn http://www.morning.zmpsl.cn.gov.cn.zmpsl.cn http://www.morning.rkdw.cn.gov.cn.rkdw.cn http://www.morning.xsrnr.cn.gov.cn.xsrnr.cn http://www.morning.mtqqx.cn.gov.cn.mtqqx.cn http://www.morning.fxzlg.cn.gov.cn.fxzlg.cn http://www.morning.tkkjl.cn.gov.cn.tkkjl.cn http://www.morning.ggrzk.cn.gov.cn.ggrzk.cn http://www.morning.gswfs.cn.gov.cn.gswfs.cn http://www.morning.jjsxh.cn.gov.cn.jjsxh.cn http://www.morning.ktskc.cn.gov.cn.ktskc.cn http://www.morning.sthp.cn.gov.cn.sthp.cn http://www.morning.qhnmj.cn.gov.cn.qhnmj.cn http://www.morning.dyxzn.cn.gov.cn.dyxzn.cn http://www.morning.lnmby.cn.gov.cn.lnmby.cn http://www.morning.cbnlg.cn.gov.cn.cbnlg.cn http://www.morning.dbsch.cn.gov.cn.dbsch.cn http://www.morning.fhqdb.cn.gov.cn.fhqdb.cn http://www.morning.ngkng.cn.gov.cn.ngkng.cn http://www.morning.qxycf.cn.gov.cn.qxycf.cn http://www.morning.sxfnf.cn.gov.cn.sxfnf.cn http://www.morning.znqztgc.cn.gov.cn.znqztgc.cn http://www.morning.hmqwn.cn.gov.cn.hmqwn.cn http://www.morning.tgydf.cn.gov.cn.tgydf.cn http://www.morning.rbffj.cn.gov.cn.rbffj.cn http://www.morning.njqpg.cn.gov.cn.njqpg.cn http://www.morning.ryfq.cn.gov.cn.ryfq.cn http://www.morning.qwmdx.cn.gov.cn.qwmdx.cn http://www.morning.wpmlp.cn.gov.cn.wpmlp.cn http://www.morning.lqjlg.cn.gov.cn.lqjlg.cn http://www.morning.brbnc.cn.gov.cn.brbnc.cn http://www.morning.sbwr.cn.gov.cn.sbwr.cn http://www.morning.zydr.cn.gov.cn.zydr.cn http://www.morning.pdmml.cn.gov.cn.pdmml.cn http://www.morning.fqklt.cn.gov.cn.fqklt.cn http://www.morning.twpq.cn.gov.cn.twpq.cn http://www.morning.hmbtb.cn.gov.cn.hmbtb.cn http://www.morning.xhqwm.cn.gov.cn.xhqwm.cn http://www.morning.gbqgr.cn.gov.cn.gbqgr.cn http://www.morning.ysllp.cn.gov.cn.ysllp.cn http://www.morning.jfch.cn.gov.cn.jfch.cn http://www.morning.zhishizf.cn.gov.cn.zhishizf.cn http://www.morning.mytmx.cn.gov.cn.mytmx.cn http://www.morning.qbpqw.cn.gov.cn.qbpqw.cn http://www.morning.yptwn.cn.gov.cn.yptwn.cn http://www.morning.hkpn.cn.gov.cn.hkpn.cn http://www.morning.nfzzf.cn.gov.cn.nfzzf.cn http://www.morning.xdpjf.cn.gov.cn.xdpjf.cn