
2.3 函数接口
上面的例子中涉及很多函数接口,例如:
◎Function
◎Consumer
◎Comparator
它们都属于函数接口,都标记了@FunctionalInterface注解。


任意一个只有抽象方法的接口都是函数接口(Functional Interface),这类接口都可以使用Lambda表达式(或方法引用)实现。函数接口只有一个抽象方法,但有很多其他方法,这些方法可归类如下。
◎静态方法:和接口有关的工具助手方法。使用static关键字实现。
◎默认方法:添加新的功能方法到已有的接口,在老的代码中,使用了该接口其他方法的代码不会受到影响。使用default关键字实现。
这也意味着从Java 8开始,接口内不仅可以有抽象方法,还可以有静态方法和默认方法。只要符合定义,即使没有标记@FunctionalInterface,它也是函数接口。当然,如果不符合函数接口的定义,那么即使标记了@FunctionalInterface,编译器也会报错,这就是@FunctionalInterface的作用。
函数接口主要位于java.util.function包下,可分成下面几类。
◎Predicate:有输入且只输出布尔值的函数。
◎Function:有输入有输出的函数。
◎Consumer:有输入无输出的函数。
◎Supplier:无输入有输出的函数。
◎Operator:输入和输出为相同类型的函数。
2.3.1 Predicate
Predicate(断言)的源码定义如下。

Lambda表达式即为test方法的实现。从test方法的定义可以看出,test方法可接收任意类型的参数T,返回值为boolean类型,可以用下面的表达式定义。

根据类型推断可缩写为Predicate<String>emptyPredicate=s->s.isEmpty()。
使用当前Predicate定义,可通过test方法执行。

输出的emptyPredicate.test("wyf")返回值为false。
1.组合Predicate
Predicate接口包含negate、and和or方法,可以重用已有的Predicate,组成复杂的Predicate。
◎negate:已有Predicate的否定。

◎and:相当于逻辑运算中的&&。

只有在i>0且i<100的情况下,test方法的返回值才为true。
◎or:相当于逻辑运算中的||。

当i>0或i<100时,test方法的返回值是true。
2.原始数据类型Predicate
Java会自动将包装类型拆包成原始数据类型,但这意味着性能的损失,所以当数据为原始数据类型时,Java提供了一些特殊的Predicate。
◎IntPredicate:当入参是int类型时,

可修改成下面的样子。

◎DoublePredicate:入参为double类型。
◎LongPredicate:入参为long类型。
3.两个参数的Predicate
Java还提供了表示两个入参的Predicate,叫作BiPredicate。

test方法可接收两个入参,类型分别为T和U。

第一个入参T类型为String(str),第二个入参U类型为Integer(len)。
2.3.2 Function
Function(函数)的源码定义如下。

Lambda表达式是apply方法的实现,apply方法可接收任意类型的参数T,返回值类型为R,可以用下面的表达式定义。

入参T类型为String(str),返回值R类型为Integer(str.length()),使用当前Function定义,可通过apply方法执行。

输出的lengthFunction.apply("wyf")返回值为3。
1.组合Function
Function接口函数提供了andThen和compose方法来组合已有的Function,组合Function的返回值仍为Function。下面定义两个将被组合的Function。

(1)andThen:新的Function是把组合中第一个函数的返回值作为第二个函数的输入。

执行时,plusFunction先执行,返回值作为multipleFunction的入参再执行,结果为16。
(2)compose:新的Function是把组合中第二个函数的返回值作为第一个函数的输入。

执行时,multipleFunction先执行,返回值作为plusFunction的入参再执行,结果为8。
2.原始数据类型Function
与Predicate一样,Function也有原始数据类型的Function,主要有3类。
第一类入参固化为函数接口,返回值类型R,仍需在泛型中定义。
◎IntFunction:入参为int类型。上面的plusFunction可修改为

◎LongFunction:入参为long类型。
◎DoubleFunction:入参为double类型。
第二类是返回值固化为函数接口,入参类型T仍需在泛型中定义。
◎ToIntFunction:返回值类型为int类型。

◎ToLongFunction:返回值类型为long类型。
◎ToDoubleFunction:返回值类型为double类型。
第三类是入参和返回值都固化为函数接口。
◎IntToLongFunction:入参为int类型,返回值为long类型。

◎IntToDoubleFunction:入参为int类型,返回值为double类型。
◎LongToIntFunction:入参为long类型,返回值为int类型。
◎LongToDoubleFunction:入参为long类型,返回值为double类型。
◎DoubleToIntFunction:入参为double类型,返回值为int类型。
◎DoubleToLongFunction:入参为double类型,返回值为long类型。
3.两个入参的Function
Java还提供了BiFunction,源码定义如下。

apply方法可接收两个参数T和U,返回值为R。可以用下面的表达式定义。

apply方法的第一个入参T类型是String(str1),第二个入参U类型是String(str2),返回值是两个字符串长度之和。执行apply方法,输出为6。
同样,BiFunction也有很多原始数据类型函数。
◎ToIntBiFunction:返回值为int类型。
◎ToLongBiFunction:返回值为long类型。
◎ToDoubleBiFunction:返回值为double类型。
2.3.3 Consumer
顾名思义,Consumer(消费者)是只消费不生产,源码定义如下。

从accept方法的定义中可以看出,accept方法可接收一个参数T,没有返回值,可以用下面的表达式定义。

accept方法可接收的参数T类型是String(str),没有返回值。
Consumer有原始数据类型接口。
◎IntConsumer:入参为int类型。
◎LongConsumer:入参为long类型。
◎DoubleConsumer:入参为double类型。
Consumer也有表示两个参数的BiConsumer接口。
◎ObjIntConsumer:第一个入参为任意类型T,第二个入参为int类型。
◎ObjLongConsumer第一个入参为任意类型T,第二个入参为long类型。
◎ObjDoubleConsumer:第一个入参为任意类型T,第二个入参为double类型。
2.3.4 Supplier
顾名思义,Supplier(提供者)是只生产不消费,源码定义如下。

get方法不接收参数,返回值为类型T,可以用下面的表达式定义。

get方法没有入参,返回值是Long类型,输出当前系统事件。
同样,Supplier也有原始数据类型接口。
◎IntSupplier:返回值是int类型。
◎LongSupplier:返回值是long类型。
◎DoubleSupplier:返回值是double类型。
◎BooleanSupplier:返回值是boolean类型。
2.3.5 Operator
Operator(操作者)是一种特殊的Function接口,它的输入和返回值是同一种类型。
1.UnaryOperator
UnaryOperator继承了Function接口,定义如下。

UnaryOperator可接收一个入参类型T,返回值也是类型T。
同样,UnaryOperator也有原始数据类型的函数接口。
◎IntUnaryOperator:入参和返回值都是int类型。
◎LongUnaryOperator:入参和返回值都是long类型。
◎DoubleUnaryOperator:入参和返回值都是double类型。
2.BinaryOperator
BinaryOperator继承了Function接口,定义如下。

BinaryOperator接收的两个入参类型都为T,返回值类型也是T。
同样,BinaryOperator也有原始数据类型的函数接口。
◎IntBinaryOperator:两个入参和一个返回值都是int类型。
◎LongBinaryOperator:两个入参和一个返回值都是long类型。
◎DoubleBinaryOperator:两个入参和一个返回值都是double类型。
2.3.6 Comparator
Comparator是比较排序所用的一个函数接口,定义如下。

◎若o1小于o2,则返回负数。
◎若o1等于o2,则返回0。
◎若o1大于o2,则返回正数。
可以用Lambda表达式来定义。

Comparator函数接口还为排序提供了comparing的静态方法,它可接收一个Function接口来获取处理数据的排序key,上面的语句可以简写成下面的样子。

2.3.7 自定义函数接口
函数接口的定义主要是看入参和返回值,前面介绍了有一个入参的Function接口和有两个入参的BiFunction接口,下面自定义一个有三个入参的TriFunction接口。

a.@FunctionalInterface标记为函数接口。
b.apply方法可接收三个入参T(t)、U(u)和W(w),返回值为R。
可以通过如下Lambda表达式调用。

第一个入参类型为String(str1),第二个入参类型为String(str2),第三个入参类型为String(str3),返回值类型为Integer。计算输出三个字符串的长度之和,输出结果为9。