Java 8 函數式接口 : Supplier、Function、Consumer、Predicate

函數式接口特點

1、三種方法

  • 唯一的抽象方法
  • 使用default定義普通方法(默認方法),通過對象調用。
  • 使用static定義靜態方法,通過接口名調用。

2、一個新註解@FunctionInterface
如果某一個接口就是爲了函數式接口而生的,使用註解@FunctionalInterface告訴編譯器這是一個函數式接口,明確這個函數中只有一個抽象方法,當你嘗試在接口中編寫多個抽象方法的時候編譯器將不允許,但是可以有多個非抽象方法。
不過Object類的方法可以定義爲抽象方法,因爲接口的實現類一定是Object的子類。

3、實現方式
JDK8以前,通過匿名內部類實現函數式接口

new Thread(new Runnable() {  
    @Override  
    public void run() {  
        System.out.println("Hello world !");  
    }  
}).start(); 

JDK8以後可以使用lambda 表達式來實現,lambda表達式就是爲了優化匿名內部類而生。

Runnable r = () -> System.out.println("task running !");
new Thread(() -> System.out.println("task running !")).start();

JDK提供的函數式接口

1. JDK 1.8之前已有函數式接口,比如:
java.lang.Runnable
java.util.concurrent.Callable
java.util.Comparator

2. JDK 1.8 新增加的函數接口包:
java.util.function.*
java.util.function 它包含了很多接口,用來支持 Java的 函數式編程,它們大致分爲五類:

類型 接口 參數 返回值 描述
供給型接口 Supplier<T> None T 沒有輸入,返回一個對象T
功能型函數式接口 Function<T, R> T R 對象轉換,T->R
消費型接口 Consumer<T> T void 改變對象T內部屬性的值
斷言型接口 Predicate<T> T boolean 進行邏輯判斷,返回boolean值
其他

供給型接口 Supplier<T>
JDK 8 源碼

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

使用

Supplier<String> supplier =  ()-> "Hello World!";
Supplier<String> supplier =  ()-> new User();

功能型函數式接口 Function<T, R>
接受一個輸入參數T,返回一個結果R。
JDK8 源碼如下

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

lambda 表達式實現Function接口

Function<String,Long> fun = str -> Long.valueOf(str);
Function<Integer,String> fun = item -> item+"";

Consumer<T> 消費型接口
An operation which accepts a single input argument and returns no result. Unlike most other functional interfaces, Consumer is expected to operate via side-effects.
一個接受單個輸入參數並且不返回結果的操作。 與大多數其他函數接口不同, Consumer接口期望通過副作用進行操作。

Consumer接口JDK8 源碼如下

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     * 對給定的參數執行此操作
     * @param t the input argument
     */
    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
		//after == null 則拋異常 NullPointerException()
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

accept()接受並改變某個對象的內部值

  user -> user.setAge(20);

Predicate<T> 斷言型接口
JDK8 源碼如下

@FunctionalInterface
public interface Predicate<T> {
	//進行某些邏輯判斷並返回一個boolean值
    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);
    }
}

lambda 表達式實現Predicate接口

Predicate<Integer> predicate = age -> age > 18;
Predicate<String> predicate = str -> str != null;

Predicate常用於集合的過濾,得到一個新的集合
Stream filter(Predicate<? super T> predicate);

List<Long> supplierIds = page.getContent().stream().map(item -> item.getSupplierId()).distinct()
					.filter(item -> item != null).collect(Collectors.toList());
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章