从企业级开发到云原生微服务:Spring Boot实战
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

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。