两千字详解Java8中必知的4个函数式接口
前言
Java8中提供了许多函数式接口,包括Function、Consumer、Supplier、Predicate等等。这4个接口就是本篇将要分享的内容,它们都位于java。util。function包下。
为什么需要知道这几个函数式接口?
因为这4个函数式接口是Java8中新增的重要接口,同时Java8的Stream新特性,也有用到这些接口,所以学习它们可以帮助我们更好地理解Stream流。
也正因为这是函数式接口,所以就可以使用Lambda表达式来写接口的实现逻辑。而且学习的过程中可以更好地理解函数式编程的思想。Function接口说明
Function这个单词的意思就有函数的意思,就数学中的yf(x),接收一个x参数,通过函数f运算后,返回一个结果y。
Function接口包含四个方法:apply(Tt):这是Function接口的主要方法,它接收一个参数并返回一个结果。同时它也是唯一的抽象的方法,剩下的都是有默认实现的(Java8中接口的抽象方法支持默认实现)。andThen(Functionafter):作用是将两个Function组合。首先执行当前函数,再执行andThen函数,并将当前函数的结果作为参数传递给andThen函数。compose(Functionbefore):同理,将两个Function组合,将先执行compose函数,再执行当前函数,并将compose函数的结果作为参数传递给当前函数。identity():返回一个执行恒等转换的函数,即返回输入参数本身。
Function接口通常用于将一个类型的值转换为另一个类型的值。apply方法Function接口的泛型,第一个参数是入参类型,第二个参数是出参类型Function接口只有一个抽象方法,就是apply(),下面利用Lambda表达式实现这个抽象方法并创建Function对象FunctionInteger,StringfunctionnumGTAnum;将5这个参数传递给function,得到返回结果Stringresultfunction。apply(5);System。out。println(result);打印:GTA5复制代码andThen和compose方法定义两个Function对象进行相关转换操作FunctionString,StringupperCasess。toUpperCase();FunctionString,StringaddPostfixss5;链式调用,将gta这个字符串参数先传递upperCase这个函数进行操作,然后将得到的结果传递给addPostfix函数进行操作,得到返回结果StringstrupperCase。andThen(addPostfix)。apply(gta);System。out。println(str);打印:GTA5复制代码identify方法
identity方法返回一个执行恒等转换的函数,该函数将输入参数原样返回。例如:FunctionString,StringidentityFunction。identity();Stringresultidentity。apply(hello);打印:hello复制代码Consumer接口说明
Consumer这个单词的意思就有消费者的意思,就把入参消费了,并不会返回结果给你。
Consumer接口包含两个方法:accept(Tt):该方法接受一个参数并执行一些操作。andThen(Consumerafter):同理,将两个Consumer组合,先后进行消费。accept方法
Consumer接口通常用于消费一个参数然后执行一些操作。例如:Consumer接口,泛型参数是入参类型,接受一个参数,并不返回结果,相当于消费了这个参数ConsumerStringconsumersSystem。out。println(s);consumer。accept(我输入什么就打印什么);打印:我输入什么就打印什么复制代码andThen方法
组合两个Consumer:ConsumerStringfirstsSystem。out。println(s5);ConsumerStringsecondsSystem。out。println(s6);先执行first这个Consumer,接着执行second这个ConsumerConsumerStringcombinationfirst。andThen(second);combination。accept(GTA);打印:GTA5GTA6复制代码Supplier接口
Supplier接口只定义了一个get()方法,该方法不接受任何参数并返回一个结果。
Supplier这个单词的意思就有供应者的意思,给我的感觉就是生产者,不用参数,直接生产一个东西给你。
Supplier接口通常用于生成一个值。例如:Supplier接口,泛型参数是出参类型,不接受参数,但是会提供结果,相当于生产了某个东西SupplierStringsupplier()提供一个我随便打的字符串给调用方;Stringtextsupplier。get();System。out。println(text);打印:提供一个我随便打的字符串给调用方复制代码Predicate接口说明
Predicate这个单词的意思就有预言,预测,谓语,谓词的意思,就是用来预测判断的。
Predicate接口包含四个方法:test(Tt):该方法接受一个参数并返回一个布尔值。and(Predicateother):与另一个Predicate进行组合,实现逻辑与操作。negate():与另一个Predicate进行组合,实现逻辑非操作。or(Predicateother):与另一个Predicate进行组合,实现逻辑或操作。test方法
Predicate接口通常用于测试一个条件是否成立。例如:Predicate接口,泛型参数是入参类型,返回布尔值PredicateStringpredicatess。contains(god23bin);booleanflagpredicate。test(god23bin能给你带来收获吗?);System。out。println(god23bin能给你带来收获吗?flag);打印:god23bin能给你带来收获吗?true复制代码and方法
为了便于演示,这里准备两个Predicate:PredicateStringstartsWithA(str)str。startsWith(A);如果传入的字符串是A开头,则返回truePredicateStringendsWithZ(str)str。endsWith(Z);如果传入的字符串是Z结尾,则返回true复制代码
使用and进行组合,与操作:PredicateStringstartsWithAAndEndsWithZstartsWithA。and(endsWithZ);System。out。println(startsWithAAndEndsWithZ。test(ABCDEFZ));trueSystem。out。println(startsWithAAndEndsWithZ。test(BCDEFGH));false复制代码negate方法
使用negate进行组合,非操作:PredicateStringnotStartsWithAstartsWithA。negate();System。out。println(notStartsWithA。test(ABCDEF));falseSystem。out。println(notStartsWithA。test(BCDEFGH));true复制代码or方法
使用or进行组合,或操作:PredicateStringstartsWithAOrEndsWithZstartsWithA。or(endsWithZ);System。out。println(startsWithAOrEndsWithZ。test(ABCDEF));trueSystem。out。println(startsWithAOrEndsWithZ。test(BCDEFGH));false复制代码那这些接口有什么应用呢?
在Stream流中就有应用上这些函数式接口。当然,当你有相似的需求时,你自己也可以应用上这些接口。下面说下Stream流中的应用。
Function接口:例如map方法,map方法就是将一个类型的值转换为另一个类型的值。map方法,将T类型的值转换成R类型的值R是返回的Stream流的元素类型,T是原先Stream流的元素类型RStreamRmap(Functionlt;?superT,?extendsRmapper);复制代码
Consumer接口:例如forEach方法forEach方法,遍历Stream流中的元素,T类型是Stream流的元素类型voidforEach(Consumerlt;?superTaction);复制代码
Supplier接口:例如generate方法生成一个无限长度的Stream流publicstaticTStreamTgenerate(SupplierTs){Objects。requireNonNull(s);returnStreamSupport。stream(newStreamSpliterators。InfiniteSupplyingSpliterator。OfRef(Long。MAXVALUE,s),false);}复制代码
Predicate接口:例如filter方法,使用Predicate进行过滤操作。过滤出Stream流中,判断结果为true的元素StreamTfilter(Predicatelt;?superTpredicate);复制代码