Java8 函數式編程之函數接口(下)

在上一篇中咱們已經介紹了什麼是功能接口以及Jdk中java.util.function下的Function的基礎用法。java

下面咱們將會介紹高階函數,什麼是高階函數呢?就是能夠定義任意同類計算的函數。 下面看個例子:bash

public class Demo{
    
    public static void main(String[] args){
        
        Function<Integer,Function<Integer,Integer>> m1 = a -> b -> a+b;
        
        Function<Integer,Integer> func = m1.apply(1);
        
        Integer x = 2;
        System.out.println("m1計算結果"+func.apply(x));//輸出3
        
        Function<Integer,Integer> func2 = m1.apply(5);
        System.out.println("m1計算結果2:"+func2.apply(x));//輸出7
    }
}
複製代碼

下面來簡單解釋一下,上面代碼中的m1是一個Function,其自己的返回值仍是一個Function,就是說,m1返回值用lambda表達式就是b->a+b。所以下面的就很容易了。app

BiFunction是是一個二元函數的接口聲明,所謂二元就是支持兩個參數。上面咱們看到的Function只接受一個參數。這就是二者之間的區別。less

public static void mian(String[] args){
    Bifunction<Integer,Integer,Integer> func = (x,y) -> x+b;
    System.out.println("x+y="+func.apply(2,3));//輸出5
}
複製代碼

須要注意的是,這個二元函數的default方法只有一個andThen方法,沒有compose方法。ide

下面列出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的一元函數
複製代碼

Operatorui

包括UnaryOperatorBinaryOperator。分別對應單元算子和二元算子this

UnaryOperator:lua

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

    /**
     * Returns a unary operator that always returns its input argument.
     *
     * @param <T> the type of the input and output of the operator
     * @return a unary operator that always returns its input argument
     */
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}
複製代碼

BinaryOperator:spa

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
    /**
     * Returns a {@link BinaryOperator} which returns the lesser of two elements
     * according to the specified {@code Comparator}.
     *
     * @param <T> 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 <T> BinaryOperator<T> minBy(Comparator<? super T> 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 <T> 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 <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
    }
}
複製代碼

算子就是一個針對同類型輸入輸出的一個映射。在此接口下,只需聲明一個泛型參數T便可。對應上面的例子:

public static void main(String[] args){

        UnaryOperator<Integer> addFunc = x -> x+1;
        System.out.println("addFunc:"+addFunc.apply(2));//輸出3

        BinaryOperator<Integer> addFunc2 = (x,y) -> x+y;
        System.out.println("addFunc2:"+addFunc2.apply(2,3));//5

        //minBy方法傳入一個Comparator接口的函數用做比較兩個數大小的規則
        BinaryOperator<Integer> min = BinaryOperator.minBy((a,b) -> a-b);
        System.out.println(min.apply(5,9));//5

        BinaryOperator<Integer> 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);
複製代碼

默認方法有andornegate,分別對應代碼中的&&||!,很簡單,就不舉例子了。

default Predicate<T> and(Predicate<? super T> other) {
    Objects.requireNonNull(other);
    return (t) -> test(t) && other.test(t);
}

default Predicate<T> negate() {
    return (t) -> !test(t);
}

default Predicate<T> or(Predicate<? super T> 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();返回boolean

DoubleSupplier:double getAsDouble();返回double

IntSupplier:int getAsInt();返回int

LongSupplier:long getAsLong();返回long
複製代碼

以上就是我對這些函數式接口的大概介紹,有什麼不對的還望指正,謝謝。

相關文章
相關標籤/搜索