JDK8--函數式接口

**

函數式接口

**
jdk1.8 函數式接口

  • java.lang.Runnable
new Thread(()->System.out.println("開啓一個線程!")).start();
  • java.util.concurrent.Callable
ExecutorService threadPool = Executors.newSingleThreadExecutor();
Future<String> future = threadPool.submit(()->"創建了一個線程");
  • java.util.Comparator
Collections.sort(list, (Comparator<Integer>) (o1, o2) -> o1.compareTo(o2));

jdk1.8 內置的函數式接口放在包 java.util.function 下,默認在jdk安裝路徑下的 src.zip 中.
這些接口,主要分4大類:

  • Consumer(類似於消費者需要傳入參數無返回值)

  • Supplier(類似於生產者不需要傳入參數,但有返回值)

  • Function(有輸入也有返回)

  • Predicate(判斷函數,有輸入也有返回,返回true or false)
    他們特點如下:

接口 參數類型 返回類型 方法 用途

  • Consumer T void void accept(T t) 對類型T參數操作,無返回結果

  • Supplier 無 T T get() 創造T類型參數

  • Function T R R apply(T t) 對類型T參數操作,返回R類型參數

  • Predicate T boolean boolean test(T t) 斷言型接口,對類型T進行條件篩選操作

Consumer 接口源碼:

@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

Consumer 表示接受單個輸入參數並且不返回結果的操作:

public class Test {
    private void test(double money, Consumer<Double> con){
        con.accept(money);
    }

    @org.junit.Test
    public void test1(){
        double money = 10000;
        test(money,m->System.out.println("這次消費了" + m + "元!"));
        System.out.println(money);
    }
}

在這裏插入圖片描述
由此可見,Consumer 的作用僅僅只是對傳入的參數進行操作,並不是真正的“消費掉了”,因爲函數式編程推崇的是不可變對象,Lambda表達式不允許修改“值”.

但Consumer的真正意義並不是簡單的實現一個無返回值的單參數方法(或者說行爲),而是由它的default方法所帶來的嵌套調用(連鎖調用),這種調用是無限次的.

public class Test {
    private void test(double money, Consumer<Double> con){
        con.accept(money);
    }

    @org.junit.Test
    public void test1(){
        double money = 10000;
        Consumer consumer = m->System.out.println("這次消費了"+m+"元");
        Consumer consumer1 = s->System.out.println("這次消費了"+s+"元");
        test(money,consumer.andThen(consumer1.andThen(consumer)));
        System.out.println(money);
    }
}

執行結果如下:
在這裏插入圖片描述

Supplier 接口源碼:

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

Supplier 沒有要求每次調用供應商時都會返回新的或不同的結果.

在這裏插入圖片描述
但這是兩種編程思想的問題,Supplier提供的是一種行爲,將行爲規範化,爲的是如果其他地方需要產生一個對象(比如100以內的整型,這當然可以直接傳入對象,但如果是一個複雜對象,這個對象的創建過程特別複雜),Supplier可以爲其提供一種產生該對象的規範行爲並直接可作爲參數傳入.

Function 接口源碼:

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}


Function ,顧名思義,接受一個參數,經過處理後,再返回一個結果,其中 andThen() 方法接受一個行爲,並將父方法處理過的結果作爲參數再處理,而 compose() 方法正好相反,它是先自己處理然後將結果作爲參數傳給父方法執行,雖然處理的都是數據,但傳入的卻是行爲.

@Test
    public  void test3(){
        Function function = str->str+"suffix";
        Function function1 = str->str+"prefix";
        System.out.println(function.apply("111"));
        System.out.println(function.andThen(function1).apply("111"));
        System.out.println(function.compose(function1).apply("111"));
    }

在這裏插入圖片描述
Predicate 接口源碼:

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);

    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);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }

簡單來說,Predicate 也是一種行爲的描述,對參入的對象作某些判斷,並返回一個boolean值,這些判斷邏輯即這個行爲的具體實現過程,則完全由使用者定義,其中還提供一些簡單的組合判斷,與、或、非以及 isEqual.
在這裏插入圖片描述

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