【Java】基础49:两个函数式接口
今天是刘小爱自学Java的第49天。
感谢你的观看,谢谢你。
话不多说,开始今天的学习:
学习两个常用函数式接口,为后面学Stream流做准备。
一、Predicate接口
Predicate,翻译过来就是断言、推断的意思
1Predicate接口及其抽象方法
一起来看看下它的源码:
①函数式接口
既然是函数式接口,就可以使用lambda表达式了。
其有一个抽象方法test,还有好几个默认方法。
②抽象方法test
参数为(T t):任意一种指定类型的数据。
返回值:boolean值。
所以该方法的作用就可以理解成:
给一个某种类型的数据进行判断,得到一个boolean值结果;至于是如何判断的?根据不同情况重写方法就好了。
2Predicate的默认方法
同样来看看它的源码:
①negate()方法
negate,翻译过来就是对立面,反面的意思。
从源码我们就可以看出:它对应逻辑运算符中的!(非)。
②or()方法
or,翻译过来也就是或者,对应逻辑运算符中的||,也就是两者的条件只要有一个满足就可以了。
③and()方法
and,翻译过来也就是并且,对应逻辑运算符中的&&,也就是两者的条件都要满足才行。
or和and方法的参数和返回值一样,也就是说可以链式编程,调用and方法后继续可以接着调用and方法。
最后默认方法我们用几个例子来一步步学习。
3默认方法:negate
现有一个需求:中文名一般都是两个字或者三个字,现判断中文名是否不大于3个字?
代码编写如下:
这是函数式编程,不知写了多少遍了。
lambda表达式表示的是什么?
是对test方法的重写,也就是说prdicate.test(name),得到的就是lambda表达式的结果,但是有了一个negate方法,那就是结果取反。
4默认方法:and
现有一个需求:
中文名不大于3个字并且必须包含有“爱”字?
①两个lambda表达式
就分别对应了method方法中的两个参数:
第一个lambda表达式:判断长度是否大于3;
第二个lambda表达式:判断是否包含“爱”
②and方法
先推断predicate1并取反,再推断predicate2,最后将两者的结果并起来。
5默认方法:or
①同样也是两个lambda表达式
和and方法一样,这样有一个好处就在于:
我只需要想判断条件有哪些,至于它们是并起来还是或起来,在①中我不用管。
②or方法
先推断predicate1并取反,再推断predicate2,最后将两者的结果或起来。
or方法和and方法非常类似,只不过对应的逻辑不一样。
二、Function接口
Function,翻译过来就是函数的意思。
如何理解函数这个概念?
说白了就是给一个参数得到一个返回值,当然也有无参无返回值的特殊情况。
1抽象方法apply
一起来看看下它的源码:
①函数式接口Function
该接口有两个泛型:前面为参数,后面为返回值。
②抽象方法apply
参数(T t):任意一种指定的数据类型。
返回值(R):同样也是任意一种指定的数据类型。
也就是说该方法的作用就是将一个类型的数据转换成另一个类型的数据,当然数据类型也有一样的特殊情况。
至于是如何转换的?在重写apply方法中写入具体的转换逻辑就可以了。
所以Function也可以将其理解成转换、交换。
现有一个需求:将String类型的数值“100”转换为Integer类型。
代码编写如下:
①lambda表达式
我这次换了一个写法,没有重新创建一个新的方法。
Function是一个接口,它是不能创建对象的,那么①中function是啥?
这是多态,父类(父接口)引用指向子类(实现类)对象。
所以再次回顾一下:lambda表达式本质上就相当于是function接口的实现类对象。
内容Integer.parseInt(t)是在干什么?
是在重写接口中的抽象方法,因为只有一个抽象方法需要重写,所以不用写方法名就知道是那个方法。
这也是为何lambda表达式的使用前提需要是函数式接口的原因。
②方法引用
因为parseInt()方法是Integer类里的一个静态方法,所以可以用类名直接引用该方法。
2默认方法andThen
现有一个需求:将 String 类型的数值“100”转换为 Integer 类型,再将该数字乘以10。
代码编写如下:
①lambda表达式
用来写具体的转换业务逻辑:
第一个:将字符串“100”转换成数字100;
第二个:将数字100乘以100。
②andThen方法
Function接口中有一个默认的andThen方法,用来进行组合操作。
就可以理解成“先做什么,再做什么”:
先function1:也就是对应第一个lambda表达式;
再function2:也就是对应第二个lambda表达式。
最后我们再来看看andThen源码:
我们根据我们上述例子来分析下源码。
例子中有function1和function2:
function2也就是源码中的after。
而function1的返回值也就是apply(t)。
源码理解也就是将function1的apply方法的返回值作为function2的apply方法的参数。
根据具体的需求,还可以继续andThen下去,这一步得到的返回值继续作为下一步的参数,这样可以无限地链式编程下去。
其中:
<? super R>表示包括R在内的任何R的父类
<? extends V>表示包括V在内的任何V的子类
这是泛型里的知识点。
总结:
谢谢你的观看。
如果可以的话,麻烦帮忙点个赞,谢谢你。