JDK8新特性-Function接口與BiFunction接口

Function 接口

  • JDK8新增的函數式接口
  • 接口只有一個抽象方法apply, 接受一個T類型參數, 返回一個R類型參數, T, R表示泛型, 可以相同
  • 除了一個抽象的apply方法之外, Function存在兩個默認的default方法, compose和andThen, 這兩個方法都是用來組合不同的Function的
  • 這個函數式接口被大量應用於集合以及Stream(流)中

apply 方法

/**
 * 輸入一個T類型的參數
 * 返回一個R類型的值
 */
R apply(T t);

compose 方法

/**
 * 接口默認方法
 * 組合兩個函數方法, 返回一個新的函數
 * before的apply方法輸入一個V類型的參數, 返回一個T類型的參數
 * 當前的Funtion的apply方法是輸入一個T類型的參數, 返回一個R類型的參數
 * 兩個函數組合之後, 返回一個新的Function, 新的Function輸入一個V類型的參數, 返回一個R類型的參數
 * 簡單來說, 入參功能 : V -> T, 當前函數功能 : T -> R, 返回函數功能 : V -> R
 */
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
    // 非空判斷
    Objects.requireNonNull(before);
    return (V v) -> apply(before.apply(v));
}

andThen 方法

/**
 * 組合兩個函數方法, 返回一個新的函數
 * after的apply方法輸入一個R類型的參數, 返回一個V類型的參數
 * 當前的Funtion的apply方法是輸入一個T類型的參數, 返回一個R類型的參數
 * 兩個函數組合之後, 返回一個新的Function, 新的Function輸入一個T類型的參數, 返回一個V類型的參數
 * 簡單來說, 入參功能 : R -> V, 當前函數功能 : T -> R, 返回函數功能 : T -> V
 */
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
    // 非空判斷
    Objects.requireNonNull(after);
    return (T t) -> after.apply(apply(t));
}

API使用樣例

    public static void main(String[] args) {
        Function<Integer, Integer> function1 = value -> value * 2;
        Function<Integer, Integer> function2 = value -> value + 3;
        Function<Integer, Integer> function3 = function1.compose(function2);
        Function<Integer, Integer> function4 = function1.andThen(function2);
        // function3,先執行function2的apply方法再執行function1的apply方法, 所以結果爲(2 + 3) * 2 = 10
        System.out.println("function3 : " + function3.apply(2));
        // function4,先執行function1的apply方法再執行function2的apply方法, 所以結果爲2 * 2 + 3 = 7
        System.out.println("function4 : " + function4.apply(2));

        Function<Integer, String> function5 = value -> "Hello World " + value;
        Function<String, List<String>> function6 = value -> new ArrayList<>(Arrays.asList(value));
        Function<Long, Integer> function7 = value -> value.intValue();
        // function8 是function6調用compose組合function5
        // function6是String->List<String>, function5是Integer->String, 所以組合之後,Function8是Integer->List<String>
        Function<Integer, List<String>> function8 = function6.compose(function5);
        // function9 是function7調用andThen方法組合function5
        // function7是Long->Integer, function5是Integer->String, 所以組合之後,Function9是Long->String
        Function<Long, String> function9 = function7.andThen(function5);
        // 輸出: [Hello World 1]
        System.out.println(function8.apply(1));
        // 輸出: Hello World 100
        System.out.println(function9.apply(100L));
     }

Stream中使用舉例

Funtion接口大量被用於集合和流中, 下面就簡單舉一個例子, 看下Function在Stream中的應用
場景 :

  • 遍歷一個List, 將其中小寫字母都轉換成大寫字母進行輸出
  • Function 接口的實現負責將小寫轉換成大寫, 代碼如下:
        List<String> list = new ArrayList<>(Arrays.asList("biluo", "huangquan", "hongchen", "zimo"));
        Function<String, String> function = item -> item.toUpperCase();
        list.stream().map(function).forEach(item -> System.out.println(item));

輸出 :

BILUO
HUANGQUAN
HONGCHEN
ZIMO

更多的用法, 需要進一步瞭解一下Stream了, 這裏只是簡單舉個栗子

BiFunction接口

  • JDK8新增函數式接口
  • 可以理解爲Function的一種擴展, Function接口接收一個參數, 返回一個參數; BiFunction接口接受兩個參數, 返回一個參數
  • 唯一的抽象方法apply, 接收兩個參數, 返回一個參數
  • 存在一個默認方法addThen, 由於apply方法接收兩個參數, 所以不存在compose方法
  • 和Function一樣, 在集合與Stream流中均有應用

apply 方法

    /**
     * 輸入兩個參數, 類型分別是T和U, 返回一個結果, 類型爲R
     * @param t 函數第一個輸入參數
     * @param u 第二個輸入參數
     * @return 返回結果
     */
    R apply(T t, U u);

andThen 方法

/**
 * 傳入一個Function類型,該Function類型輸入參數爲R, 返回結果類型爲V
 * 當前BiFunction的apply函數輸入參數類型爲T, U; 返回結果類型爲R
 * 將兩個參數組合之後返回一個新的BiFunction方法, 輸入參數是T,U,返回結果類型爲V
 * 簡單來說就是當前的BiFunction是(T, U) -> R, 傳入的Function是R -> V
 * 所以組合後的新的Function是(T, U) -> V, 即把BiFunction的返回結果作爲入參再傳入Function中
 */
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
    Objects.requireNonNull(after);
    return (T t, U u) -> after.apply(apply(t, u));
}

BiFunction沒有Compose方法是因爲BiFunction的apply方法要接收兩個參數, 而不管是Function還是BiFunction乃至所有的Java方法, 返回結果都只有一個

API代碼樣例

    public static void main(String[] args) {
        BiFunction<Integer, Integer, Integer> biFunction = (num1, num2) -> num1 + num2;
        // 輸出 : 5
        System.out.println(biFunction.apply(2, 3));
        Function<Integer,Integer> function = num -> num * num;
        // newBiFunction的apply(num1, num2)方法等於function.apply(biFunction(num1, num2))
        BiFunction<Integer, Integer, Integer> newBiFunction = biFunction.andThen(function);
        // 輸出 : 25
        System.out.println(newBiFunction.apply(2, 3));

        BiFunction<Integer, Integer, List<Integer>> biFunction2 = (num1, num2) -> new ArrayList<>(Arrays.asList(num1, num2));
        Function<List<Integer>,String> function2 = list -> list.toString();
        BiFunction<Integer, Integer, String> newBiFunction2 = biFunction2.andThen(function2);
        System.out.println(newBiFunction2.apply(1, 2));
    }

集合中使用舉例

HashMap中的compute方法接收一個BiFunction類型的參數

        Map<String, String> map = new HashMap<>();
        map.put("name", "qiyexue");
        BiFunction<String, String, String> biFunction = (k, v) -> k + " : " + map.get(k).toUpperCase();
        System.out.println(map.compute("name", biFunction));

輸出 :

name : QIYEXUE

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章