12. Java入门之函数式接口是什么?常用函数式接口的介绍与使用

1. 函数式接口概述

在之前介绍Lambda表达式的文章中提到了函数式接口,那时候只是顺带一嘴,现在来详细了解一下函数式接口的相关内容

1.1 概念与定义

有且只有一个抽象方法的接口被称为函数式接口,该接口中可以包含其他的方法(默认,静态,私有),但注意是抽象方法只有一个

假如我想定义一个函数式接口,那么有什么办法可以检查我所书写的代码防止写错呢?还记得注解吗?这里有一个@FunctionalInterface注解,该注解可以检测接口是否是一个函数式接口

举个例子,这里我特意写了两个抽象方法,那么该注解就会报错提醒我们没有正确定义函数式接口
在这里插入图片描述

1.2 使用与优化

函数式接口怎么使用呢?这里不要糊涂了,函数式接口的本质还是一个接口,你可以创建一个接口的实现类重写其中的抽象方法

下面给出一个根据日志等级打印日志的例子,当日志等级为1的时候才打印日志
在这里插入图片描述
显然当日志等级是2(即如图代码)的时候是不打印的,但是细心观察一下,即使他没有打印,str1和str2字符串有没有拼接了呢?其实是有的,是拼接好再传到showLog方法中,那么既然等级不符合就没有打印,那就意味着这个字符串白拼接了对不?那就会存在程序的性能浪费

那怎么解决这个问题呢?Lambda表达式他有一个延迟加载的特点,但其使用前提是必须存在函数式接口,因此我们来创建一个函数式接口
在这里插入图片描述
再使用一下这个函数式接口
在这里插入图片描述
这样子即使在调用showLog方法时候已经把str1str2传进去了,但是还是没有拼接,等待等级判断通过后再执行,这就是Lambda表达式的延迟加载特性,有同学可能会觉得这不是把简单的事情复杂化吗?其实从某种意义上来说确实是这样,但它也确实可以起到避免性能浪费的作用,弱化了new对象的操作,节省了内存,在后续的常用函数式接口介绍中同样使用Lambda表达式进行介绍

2. 常用的函数式接口

java.util.function包中,有很多JDK内置的函数式接口,下面将介绍几个最为常用的函数式接口(注意是在JDK 1.8开始才有这个特性)

2.1 Supplier接口

public interface Supplier<T>:代表结果供应商。 

该接口中只包含一个无参的方法

public T get():用来获取一个泛型参数指定类型的对象数据

Supplier< T > 接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据

功能很简单,理解很抽象,那怎么搞呢?来看个例子,现在需求是求一个数组的最大值,要求使用Suppiler接口作为方法产生类型,通过Lambda表达式求出int数组中的最大值(注意泛型接口需要使用Integer包装类)

这里直接看示例代码
在这里插入图片描述

2.2 Consumer接口

public interface Consumer<T>:表示接受单个输入参数并且不返回结果的操作。  

该接口中有一个无参的方法和一个默认方法

public void accept(T t):对给定的参数执行此操作。  
public default Consumer<T> andThen(Consumer<? super T> after):返回一个组合的 Consumer ,按顺序执行该操作,然后执行 after操作。  

Consumer< T > 接口被称之为消费型接口,指定接口的泛型是什么类型,那么就可以使用接口中的accept方法消费什么类型的数据,具体怎么消费就需要自定义

而其默认方法则是可以把两个Consumer接口组合在一起对数据进行消费,谁写在前边就先消费谁,其调用格式con1.andThen(con2).accept(s)

同样的,功能很简单,理解很抽象,那怎么搞呢?来看个例子,现在需求是有一个字符串数组中存有多条个人信息,按照“姓名:xxx,年龄:xxx。”的格式把信息打印出来,要求将打印姓名的动作作为第一个Consumer接口的示例,将打印年龄的动作作为第二个Consumer接口的示例,将两个Consumer接口拼接在一起

这里直接看示例代码
在这里插入图片描述

2.3 Predicate接口

public interface Predicate<T>:表示一个参数的谓词(布尔值函数)。

该接口中包含一个无参的方法和三个默认方法

public boolean test(T t):在给定的参数上评估这个谓词。  
public default Predicate<T> and(Predicate<? super T> other):返回一个组合的谓词,表示该谓词与另一个谓词的短路逻辑AND。
public default Predicate<T> or(Predicate<? super T> other):返回一个组合的谓词,表示该谓词与另一个谓词的短路逻辑或。  
public default Predicate<T> negate():返回表示此谓词的逻辑否定的谓词。  

Predicate< T > 接口就是用来对某种数据类型的数据进行判断,接口中的test方法就是用来制定判断规则并把结果返回

其三个默认方法其实就是相对三个逻辑——与、或、非,这个概念应该很好理解,下面直接来看个例子感受一下

现在需求是有一个数组中有多条个人信息,我需要筛选其中名字为3个字母的女生,因为需要满足两个条件,因此可以使用两个Predicate接口,并且使用and方法连接在一起

这里直接看示例代码
在这里插入图片描述
下面看看运行结果
在这里插入图片描述

2.4 Function接口

public interface Function<T,R>:表示接受一个参数并产生结果的函数。

该接口中只包含一个无参的方法和一个默认方法

public R apply(T t):将此函数应用于给定的参数。 
public default <V> Function<T,V> andThen(Function<? super R,? extends V> after):返回一个组合函数,首先将该函数应用于其输入,然后将 after函数应用于结果。  

Function< T , R > 接口被用作转换数据类型的,可调用其apply方法把T数据类型的数据转换为R数据类型的数据,但转换规则需要自定义

另外,其默认方法也是把两个Function接口连接起来,第二个Function接口会把第一个Function接口的输出结果作为输入,也可认为这是链式组合(类似方法的链式调用)

老规矩,直接看例子,这个例子的需求是把一个字符串中的个人信息中的年龄抽取出来,把该年龄转化为整形数据,然后对这个年龄进行加一,然后最终返回字符串数据

这里直接看示例代码
在这里插入图片描述
来看看输出结果
在这里插入图片描述

几个例子下来,感受到我前面所说的简单事情复杂化了吧,但总是守恒的,你代码量增加了,就有机会提高所书写程序的性能

好好体会吧,溜了溜了~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值