在上一篇中我们已经介绍了什么是功能接口以及Jdk中java.util.function
下的Function的基础用法。
下面我们将会介绍高阶函数,什么是高阶函数呢?就是可以定义任意同类计算的函数。 下面看个例子:
public class Demo{ public static void main(String[] args){ Function> m1 = a -> b -> a+b; Function func = m1.apply(1); Integer x = 2; System.out.println("m1计算结果"+func.apply(x));//输出3 Function func2 = m1.apply(5); System.out.println("m1计算结果2:"+func2.apply(x));//输出7 }}复制代码
下面来简单解释一下,上面代码中的m1是一个Function,其本身的返回值还是一个Function,就是说,m1返回值用lambda表达式就是b->a+b
。因此下面的就很容易了。
BiFunction是是一个二元函数的接口声明,所谓二元就是支持两个参数。上面我们看到的Function只接受一个参数。这就是两者之间的区别。
public static void mian(String[] args){ Bifunctionfunc = (x,y) -> x+b; System.out.println("x+y="+func.apply(2,3));//输出5}复制代码
需要注意的是,这个二元函数的default方法只有一个andThen
方法,没有compose
方法。
下面列出Function相关的接口:
BiFunction :R apply(T t, U u);接受两个参数,返回一个值,代表一个二元函数DoubleFunction :R apply(double value);只处理double类型的一元函数IntFunction :R apply(int value);只处理int参数的一元函数LongFunction :R apply(long value);只处理long参数的一元函数ToDoubleFunction:double applyAsDouble(T value);返回double的一元函数ToDoubleBiFunction:double applyAsDouble(T t, U u);返回double的二元函数ToIntFunction:int applyAsInt(T value);返回int的一元函数ToIntBiFunction:int applyAsInt(T t, U u);返回int的二元函数ToLongFunction:long applyAsLong(T value);返回long的一元函数ToLongBiFunction:long applyAsLong(T t, U u);返回long的二元函数DoubleToIntFunction:int applyAsInt(double value);接受double返回int的一元函数DoubleToLongFunction:long applyAsLong(double value);接受double返回long的一元函数IntToDoubleFunction:double applyAsDouble(int value);接受int返回double的一元函数IntToLongFunction:long applyAsLong(int value);接受int返回long的一元函数LongToDoubleFunction:double applyAsDouble(long value);接受long返回double的一元函数LongToIntFunction:int applyAsInt(long value);接受long返回int的一元函数复制代码
Operator
包括UnaryOperator
和BinaryOperator
。分别对应单元算子和二元算子
UnaryOperator:
@FunctionalInterfacepublic interface UnaryOperatorextends Function { /** * Returns a unary operator that always returns its input argument. * * @param the type of the input and output of the operator * @return a unary operator that always returns its input argument */ static UnaryOperator identity() { return t -> t; }}复制代码
BinaryOperator:
@FunctionalInterfacepublic interface BinaryOperatorextends BiFunction { /** * Returns a {@link BinaryOperator} which returns the lesser of two elements * according to the specified {@code Comparator}. * * @param the type of the input arguments of the comparator * @param comparator a {@code Comparator} for comparing the two values * @return a {@code BinaryOperator} which returns the lesser of its operands, * according to the supplied {@code Comparator} * @throws NullPointerException if the argument is null */ public static BinaryOperator minBy(Comparator comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; } /** * Returns a {@link BinaryOperator} which returns the greater of two elements * according to the specified {@code Comparator}. * * @param the type of the input arguments of the comparator * @param comparator a {@code Comparator} for comparing the two values * @return a {@code BinaryOperator} which returns the greater of its operands, * according to the supplied {@code Comparator} * @throws NullPointerException if the argument is null */ public static BinaryOperator maxBy(Comparator comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; }}复制代码
算子就是一个针对同类型输入输出的一个映射。在此接口下,只需声明一个泛型参数T即可。对应上面的例子:
public static void main(String[] args){ UnaryOperatoraddFunc = x -> x+1; System.out.println("addFunc:"+addFunc.apply(2));//输出3 BinaryOperator addFunc2 = (x,y) -> x+y; System.out.println("addFunc2:"+addFunc2.apply(2,3));//5 //minBy方法传入一个Comparator接口的函数用作比较两个数大小的规则 BinaryOperator min = BinaryOperator.minBy((a,b) -> a-b); System.out.println(min.apply(5,9));//5 BinaryOperator max = BinaryOperator.maxBy((a,b) -> a-b); System.out.println(max.apply(5,9));//9 }复制代码
还有就是其他的一下基础的扩展算子,一看就知道什么意思就不细说了。
LongUnaryOperator:long applyAsLong(long operand);IntUnaryOperator:int applyAsInt(int operand);DoubleUnaryOperator:double applyAsDouble(double operand);DoubleBinaryOperator:double applyAsDouble(double left, double right);IntBinaryOperator:int applyAsInt(int left, int right);LongBinaryOperator:long applyAsLong(long left, long right);复制代码
Predicate
Predicate是谓词函数,很明显了,所谓谓词,就是返回值为Boolean类型的函数。其抽象方法是一个test
,下面是源码:
/** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */boolean test(T t);复制代码
默认方法有and
、or
和negate
,分别对应代码中的&&
、||
和!
,很简单,就不举例子了。
default Predicateand(Predicate other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t);}default Predicate negate() { return (t) -> !test(t);}default Predicate or(Predicate other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t);}复制代码
Predicate的其他接口函数:
BiPredicate:boolean test(T t, U u);接受两个参数的二元谓词DoublePredicate:boolean test(double value);入参为double的谓词函数IntPredicate:boolean test(int value);入参为int的谓词函数LongPredicate:boolean test(long value);入参为long的谓词函数复制代码
Consumer
见文知意,消费者,肯定就是消费掉了,没有返回结果喽~
/** * Performs this operation on the given argument. * * @param t the input argument */void accept(T t);复制代码
这也就说明,在我们平时的代码中所有的无返回值类型,且一个参数的实体方法都是这个函数接口的“映射”啦,哈哈,还记得前面说的“映射”是什么意思吗? 这个也很简单,例子就不写了。
看看其他的一些Consumer:
BiConsumer:void accept(T t, U u);接受两个参数DoubleConsumer:void accept(double value);接受一个double参数IntConsumer:void accept(int value);接受一个int参数LongConsumer:void accept(long value);接受一个long参数ObjDoubleConsumer:void accept(T t, double value);接受一个泛型参数一个double参数ObjIntConsumer:void accept(T t, int value);接受一个泛型参数一个int参数ObjLongConsumer:void accept(T t, long value);接受一个泛型参数一个long参数复制代码
Supplier
有了上边的消费者,那肯定也就有生产者了,既然是生产者,那肯定就是不需要参数,自己生产东西并返回喽~
/** * Gets a result. * * @return a result */ T get();复制代码
只有一个无参get
方法,并返回T
类型。没有提供其他默认方法。看其他的博客中有的人说这个函数接口不是为了说明一个参数空间到结果空间的映射,而是要表达一种生产能力。细想我个人觉得说的也蛮好。可以想象我们用过的工厂方法。
其他的一些Supplier:
BooleanSupplier:boolean getAsBoolean();返回booleanDoubleSupplier:double getAsDouble();返回doubleIntSupplier:int getAsInt();返回intLongSupplier:long getAsLong();返回long复制代码
以上就是我对这些函数式接口的大概介绍,有什么不对的还望指正,谢谢。